Search code examples
cdynamic-memory-allocationfreeglibcpointer-arithmetic

Free pointer offset no longer valid?


I could have sworn this code should work, but it seems now it segfaults. Anyone know if this has always been the case or a change in glibc?


   ....
   char *tmp = malloc(50);
   tmp = &tmp[10];
   free(tmp);   // segfault
   // I thought as long as the pointer was within a valid memory block,   
   // the free was valid. Obviously I know not to double free, but this   
   // means any pointer offsets must be kept along with the original malloced 
   // pointer for the free operation.

Solution

  • This code snippet

       char *tmp = malloc(50);
       tmp = &tmp[10];
       free(tmp);   // segfault
       // I thought as long as the
    

    is invalid because after this statement

       tmp = &tmp[10];
    

    the pointer tmp does not have the address of the extent of the dynamically allocated memory. So the next statement

    free(tmp);
    

    invokes undefined behavior.

    From the C Standard (7.22.3.3 The free function)

    Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

    You could write

       tmp = &tmp[10];
       //...
       free(tmp - 10 );
    

    Or it seems what you need is to reallocate the early allocated memory like

       char *tmp = malloc(50);
       char *tmp2 = realloc( tmp, 10 );
    
       if ( tmp2 != NULL ) tmp = tmp2;