There is the following structure:
typedef struct _line_t { char *data; size_t length; size_t lineno; struct _line_t *next; struct _line_t *prev; } line_t; As you can guess, it is intended to organize a coherent list of strings (do not ask why I need such a crutch and why I cannot use C ++).
There is a function for creating such a line (it allocates memory for the structure and sets the fields. I will not give it here), as well as the function for deleting (freeing memory).
The last one looks like this:
void lines_delete(line_t *begin) { if(!begin) return; line_t *cur = begin, *prev; while(cur) { prev = cur; cur = cur->next; if(prev->data) free(prev->data); free(prev); prev->lineno += 1; //Для теста } } The above code does not fall, but I have known C not so long ago and decided to check with the debugger:
Breakpoint 1, lines_delete (begin=0x6032a0) at line.c:21 21 if(!begin) (gdb) n 24 line_t *cur = begin, *prev; (gdb) n 26 while(cur) { (gdb) n 27 prev = cur; (gdb) n 28 cur = cur->next; (gdb) n 30 if(prev->data) (gdb) n 31 free(prev->data); (gdb) n 33 free(prev); (gdb) n 34 prev->lineno += 1; (gdb) n 26 while(cur) { (gdb) Those. did you understand, yes? I release the prev , and then calmly turn to the already freed memory. After line 33, the debugger "says" that the memory is not released. It is noteworthy that prev-> data = 0x0, i.e. the data (char array) was freed, but the string (structure) itself was not. I'm confused.
UPD : In the function lines_data passed such a connected list of three nodes (ie, three structures) and accidentally noticed that not all prev-> data are released. See (continuation of output from gdb):
26 while(cur) { (gdb) print prev->data $1 = 0x0 (gdb) n 27 prev = cur; (gdb) n 28 cur = cur->next; (gdb) n 30 if(prev->data) (gdb) n 31 free(prev->data); (gdb) n 33 free(prev); (gdb) n 34 prev->lineno += 1; (gdb) print prev->data $2 = 0x603290 "" (gdb) That is, the data of the first line is released (becomes 0x0), and the data of the second line is not released, but becomes empty (as the debugger says).
Also, gdb allows you to do this (see below), which means that the memory is not 100% freed. Continuing the output:
(gdb) print prev->data $2 = 0x603290 "" (gdb) set prev->data = "Hello" (gdb) Now I'm completely confused, my code lives as it wants and does what it wants?
free(prev); prev->lineno += 1;free(prev); prev->lineno += 1;- first freeing the memory, and then accessing it - is strictly forbidden ... And yet - freeing the memoryfree(prev)does not makeprevnull pointer. - Harryfreeperfectly responds to the null pointer. Additional verification is not required. - αλεχολυτ