https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80532
Bug ID: 80532 Summary: warning on pointer access after free Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- Using the value of a pointer that points to an object whose lifetime has ended is undefined, and a common source of bugs. In the following test case, function free_list shows an example of one such bug (courtesy of Kernighan & Ritchie) where a freed pointer is dereferenced. Function foobar shows another example. That example is interesting because it shows that GCC is smart enough to eliminate the first call to memset (because the lifetime of the object the pointer points ends with the subsequent call to free) but it doesn't eliminate the second call to free or the second call to memset, even though that operate on an object whose lifetime has ended and will almost certainly corrupt the heap. GCC also doesn't warn on those calls. It would be a useful feature if GCC did both: warn and eliminate the undefined calls/accesses. $ cat c.c && gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout c.c #include <stdlib.h> #include <string.h> struct node { struct node *next; int value; }; void free_list (struct node *head) { struct node *p; for (p = head; p != 0; p = p->next) free (p); } void foobar (void *p, unsigned n) { memset (p, 0, n); free (p); free (p); memset (p, 0, n); } ;; Function free_list (free_list, funcdef_no=14, decl_uid=2614, cgraph_uid=14, symbol_order=14) Removing basic block 5 Removing basic block 6 Removing basic block 7 Removing basic block 8 free_list (struct node * head) { struct node * p; <bb 2> [15.00%]: if (head_3(D) != 0B) goto <bb 3>; [85.00%] else goto <bb 4>; [15.00%] <bb 3> [85.00%]: # p_9 = PHI <p_6(3), head_3(D)(2)> free (p_9); p_6 = p_9->next; if (p_6 != 0B) goto <bb 3>; [85.00%] else goto <bb 4>; [15.00%] <bb 4> [15.00%]: return; } ;; Function foobar (foobar, funcdef_no=15, decl_uid=2622, cgraph_uid=15, symbol_order=15) foobar (void * p, unsigned int n) { long unsigned int _1; <bb 2> [100.00%]: _1 = (long unsigned int) n_2(D); free (p_4(D)); free (p_4(D)); memset (p_4(D), 0, _1); [tail call] return; } tmp$