@@ -107,31 +107,48 @@ TEST_CASE("Basic CSVReader Iterator Test", "[read_ints_iter]") {
107107// ! [CSVReader Iterator 1]
108108
109109// ! [CSVReader Iterator 2]
110- TEST_CASE (" CSVReader Iterator + std::max_elem" , " [iter_max_elem]" ) {
111- SECTION (" Find Max Element with std::max_element" ) {
110+ /* *
111+ * IMPORTANT: CSVReader::iterator is std::input_iterator_tag (single-pass)
112+ * to support streaming large files with bounded memory usage.
113+ *
114+ * Algorithms requiring ForwardIterator (like std::max_element) may appear
115+ * to work with small files, but cause heap-use-after-free when data spans
116+ * multiple RawCSVData chunks that get freed as the iterator advances.
117+ *
118+ * CORRECT approach: Copy to vector first, then use algorithms.
119+ */
120+ TEST_CASE (" CSVReader Iterator + Algorithms Requiring ForwardIterator" , " [iter_algorithms]" ) {
121+ SECTION (" std::max_element - CORRECT approach using vector" ) {
112122 // The first is such that each value in the ith row is the number i
113123 // There are 100 rows
114- CSVReader r1 (" ./tests/data/fake_data/ints.csv" );
124+ CSVReader reader (" ./tests/data/fake_data/ints.csv" );
125+
126+ // Copy rows to vector to enable ForwardIterator algorithms
127+ auto rows = std::vector<CSVRow>(reader.begin (), reader.end ());
128+ REQUIRE (rows.size () == 100 );
115129
116130 // Find largest number
117- auto int_finder = [](CSVRow& left, CSVRow& right) {
131+ auto int_finder = [](const CSVRow& left, const CSVRow& right) {
118132 return (left[" A" ].get <int >() < right[" A" ].get <int >());
119133 };
120134
121- auto max_int = std::max_element (r1 .begin (), r1 .end (), int_finder);
135+ auto max_int = std::max_element (rows .begin (), rows .end (), int_finder);
122136 REQUIRE ((*max_int)[" A" ] == 100 );
123137 }
124138
125- SECTION ( " Find Max Element with std::max_element - Large File" ) {
139+ SECTION ( " std::max_element - Large File using vector " ) {
126140 // The second file is a database of California state employee salaries
127- CSVReader r2 (" ./tests/data/real_data/2015_StateDepartment.csv" );
141+ CSVReader reader (" ./tests/data/real_data/2015_StateDepartment.csv" );
142+
143+ // Copy rows to vector to enable ForwardIterator algorithms
144+ auto rows = std::vector<CSVRow>(reader.begin (), reader.end ());
128145
129146 // Find highest salary
130- auto wage_finder = [](CSVRow& left, CSVRow& right) {
147+ auto wage_finder = [](const CSVRow& left, const CSVRow& right) {
131148 return (left[" Total Wages" ].get <double >() < right[" Total Wages" ].get <double >());
132149 };
133150
134- auto max_wage = std::max_element (r2 .begin (), r2 .end (), wage_finder);
151+ auto max_wage = std::max_element (rows .begin (), rows .end (), wage_finder);
135152
136153 REQUIRE ((*max_wage)[" Total Wages" ] == " 812064.87" );
137154 }
0 commit comments