Fix mutation of input iterators in seq_arr_erase_it

The seq_arr_erase_it function was modifying start_it during the free_func loop,
which led to incorrectly apply the free_func on the whole array.

This commit makes sure the elements "freed" are only those in the range and not the whole seq_arr.

* Fixes the logic by introducing a temporary iterator for the free loop,
  preserving start_it and end_it for correct offset calculations.

* Adds a regression test in test_seq_arr to verify that only the selected
  subrange is erased and that free_func is called exactly on that range.
This commit is contained in:
Guido Casati
2025-06-17 23:50:43 +02:00
parent 8c0641c676
commit a8f8244b09
2 changed files with 24 additions and 5 deletions
+4 -5
View File
@@ -123,11 +123,10 @@ void seq_arr_erase_it(seq_arr_t* arr, void* start_it, void* end_it, void (*free_
return;
if (free_func != NULL) {
void* start_it = seq_arr_front(arr);
void* end_it = seq_arr_end(arr);
while (start_it != end_it) {
free_func(start_it);
start_it = seq_arr_next(arr, start_it);
void* it = start_it;
while (it != end_it) {
free_func(it);
it = seq_arr_next(arr, it);
}
}
+20
View File
@@ -36,6 +36,13 @@ static int compar(const void* m0, const void* m1)
return 1;
}
static int free_func_call_count = 0;
static void dummy_free_func(void* it)
{
++free_func_call_count;
}
int main()
{
seq_arr_t arr = {0};
@@ -83,6 +90,19 @@ int main()
void* it = bsearch(&key, base, nmemb, size, compar);
assert(seq_arr_dist(&arr, seq_arr_front(&arr), it) == 4);
// Regression test: erase a partial range only
// Erase 92, 93, 94 (i.e., indices 1 to 3)
int* start = seq_arr_at(&arr, 1);
int* end = seq_arr_at(&arr, 4);
seq_arr_erase_it(&arr, start, end, dummy_free_func);
// Now values should be: [91, 95, 96, 97, 98, 99]
assert(free_func_call_count == 3);
assert(seq_arr_size(&arr) == 6);
assert(*(int*)seq_arr_at(&arr, 0) == 91);
assert(*(int*)seq_arr_at(&arr, 1) == 95);
assert(*(int*)seq_arr_at(&arr, 5) == 99);
// Free data structure
seq_arr_free(&arr, NULL);