The problem is that my code is not so small so I will post only fragments of it, let me know if more of it is needed for the question to be valid.
The program uses library with various sorting algorithms (18 of them), and applies them to an unsorted array. User can select array size and how many arrays will be tested.
If I select, for example, 100arrays of 1000 elements (18*100 = 1800 times algorithms sort the array), the code works. If it is the other way, ie 1000 arrays of say 10 elements, 1000 * 18 = 18 000 sortings, then it crashes with "double free or corruption".
The question is not as much as where the problem lies, but firstly, how to debug it correctly.
Here is the function which gets a function pointer (func) of sorting algorithm, sorts the elements, checks if sorted, adds appropriate data to "Iteration" struct, and then frees both "target" (array to be sorted) and "Iter" (Iterations struct).
void test_sort(int* data, int size, sort_pointer func, Algorithm* Algo, int no)
{
count_ncomp = 0;
count_assign = 0;
begin = clock();
int* target = NULL;
target = malloc(size * sizeof(int));
if (!target)
die("Memory error.");
memcpy(target, data, size * sizeof(int));
Iteration* Iter = malloc(sizeof(Iteration));
Iter->no = no;
if (is_sorted(func(target, size), size)) {
end = clock();
clocks = (double)(end - begin);
time_spent = clocks / CLOCKS_PER_SEC;
Iter->is_sorted = 1;
Iter->comp_count = count_ncomp;
Iter->assign_count = count_assign;
Iter->clocks_total = clocks;
Iter->time_spent = time_spent;
} else {
Iter->is_sorted = 0;
debug("Not sorted, no: %d", no);
};
Algo->iterations[no - 1] = Iter;
if (target == NULL) {
debug("Target is NULL");
}
debug("before target1 free");
debug("NO: %d", no);
debug("pointer %p", target);
free(target);
free(Iter);
debug("after target1 free");
/*target = NULL;*/
}
Here is the list of data structures:
typedef struct {
int no;
int is_sorted;
int comp_count;
int assign_count;
double clocks_total;
double time_spent;
} Iteration;
typedef struct {
char* type;
char* complexity;
int iter_count;
int rank;
int avg_comp;
int avg_assign;
double avg_clocks;
double avg_time;
Iteration* iterations[MAX_ITER];
} Algorithm;
Here is the start of the program:
Starting program: /home/riddle/tmp1/pratybos12
Mem used total: 0
How many arrays would you like to test? > 1000
What is the size of each array? > 10
What is the minimum number in each array? > 1
What is the maximum number in each array? > 10
How many repeating values there will be AT LEAST? > 0
Here is the running program:
DEBUG pratybos12.c:537: NO: 374
DEBUG pratybos12.c:538: pointer 0x55899fe8cb10
*** Error in `./pratybos12': double free or corruption (out): 0x000055899fe8cae0 ***
[1] 3123 abort (core dumped) ./pratybos12
GDB output (I get a crash always on no=374):
DEBUG pratybos12.c:542: after target1 free
DEBUG pratybos12.c:535: before target1 free
DEBUG pratybos12.c:537: NO: 374
DEBUG pratybos12.c:538: pointer 0x555555760b10
Breakpoint 1, test_sort (data=0x555555760ab0, size=10, func=0x555555558c04 <bubble_sort_b_and_c_and_e_and_f>, Algo=0x55555575ff00, no=374) at pratybos12.c:541
541 free(Iter);
(gdb) print Iter
$3 = (Iteration *) 0x555555760ae0
(gdb) c
Continuing.
*** Error in `/home/riddle/tmp1/pratybos12': double free or corruption (out): 0x0000555555760ae0 ***
Program received signal SIGABRT, Aborted.
0x00007ffff7a54860 in raise () from /usr/lib/libc.so.6
I've read many posts suggesting testing it with Valgrind, however, running with Valgrind, this crash does not arise.
I know that I have posted very little info, please keep me updated to what more is needed.
The main question is how to debug. How do I check if the pointer before freeing points to something valid, is the memory accessible, etc.
These two lines from the function:
Algo->iterations[no - 1] = Iter;
...
free(Iter);
First you make Algo->iterations[no - 1]
point to the same memory that Iter
is pointing two, so you have two pointers pointing to the same memory. Then you free the memory, making both pointers invalid.
If you want to use the pointer later you can't free it.