This isn't really an answer to how free works, but I would do something along these lines:
char * trim_realloc(char * str) {
char * p = str;
char * e;
char * ne; // new end
char * r;
size_t len;
// Since you put this level of error testing in your program
if (!str) {
return str; // str is NULL
}
while (*p || isspace(*p) ) {
p++;
}
len = strlen(p);
e = p + len;
ne = e;
while (ne > p) {
if (isspace(*ne)) {
*ne = 0;
ne--;
} else {
break;
}
}
if (p == str) {
if (e != ne) {
return realloc(str, len+1); // only tail trim -- you could just return str here
} else {
return str; // no actual trim
}
} else {
r = strdup(p);
free(str); // str is the head of the string, so that's what we have to free
return r;
}
}
You should note my comment on the line with realloc
Since I zeroed out trailing space anyway (and since many realloc implementations only worry about "is it big enough", not "is there too much extra space") you could have just let the buffer that your string lived in take up too much space at the end. It's still \0 terminated at the correct spot (unless there's bugs in my untested code, which there could be).
Other things you could do would be to just move the string to the beginning of the buffer and then trim the tail, so that:
" cat "
went through the steps:
"c cat "
"ca cat "
"catcat "
"cat at "
"cat t "
"cat "
before you started trimming the tail.
Now, back to how free works -- free needs to be passed either NULL or a value that one of the heap allocation functions passed to you. Some heap allocation libraries are implemented so that when malloc allocates data the size of that data chunk is stored in the bytes just before the address that malloc returns, and when you call free the bytes just in front of that pointer are used to determine what the size of that memory chunk actually is. If you pass the something that was not returned by malloc (or calloc, or realloc, or similar) then free may look in the wrong place and use whatever it finds there as the size of the chunk you are freeing -- and nothing good comes of this.