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.
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;