I am using linux 64 bit having glibc
ldd (Ubuntu EGLIBC 2.19-0ubuntu6.15) 2.19
This my code
int main (int argc , char** argv){
char *first , *second;
first = malloc(16);
second = malloc(16);
free(first);
free(second);
}
The problem is I studied on the internet that when free is called it clears the prev_in_use bit of the next chunk and below is the memory region of those 2 chunks after 1st call to free.
gdb-peda$ x/20gx 0x602010-16
0x602000: 0x0000000000000000 0x0000000000000021
0x602010: 0x0000000000000000 0x0000000000000000
0x602020: 0x0000000000000000 0x0000000000000021
0x602030: 0x0000000000000000 0x0000000000000000
0x602040: 0x0000000000000000 0x0000000000020fc1
0x602050: 0x0000000000000000 0x0000000000000000
Now the problem is I studied that the prev_in_use bit of the next adjacent chunk is cleared and the prev_size of the next chunk will contain the size of this freed chunk but from the above output neither prev_in_use bit is cleared nor size of this chunk is written in next chunk prev_size field.
What is the problem ? Any help will be appreciated.
The thing is that glibc is a lil' bit more complicated than that. It uses several methods to store free chunks. In the example you are showing, because of the size of the chunks that you are using, they are going to the tcache.
The glibc has the problem that its malloc implementation (the ptmalloc2 algorithm) varies a lot between versions. You should have included the glibc version you are using. Either way, assuming your ubuntu is up to date you probably are using glibc 2.35. You can see below the code for
_int_free(), which is the one that implements free()'s main functionality.Immediately after a few superficial checks the function sees if that chunk is of a size that would make it eligible to be placed in the tcache. This is done with csize2tidx (which means "chunk size to tcache index"), this is because the tcache has several bins, one for a different chunk size, so what this macro does is take a size and tell the index of the tcache bin that size corresponds, then we check if that index does actually exist, which effectively sets a limit on the size a chunk may have before being put in the tcache, this limit is, in x64 and with a typical configuration, 1024.
Now the important part, you can see that if the chunk has an appropriate size and its tcache bin isn't full (a tcache bin is full with 7 chunks), the chunks is placed there and the prev_inuse bit of the next contiguous chunks never gets updated.
This is because tcache'd chunks aren't supposed to be merged with other chunks so, in order to prevent them from being consolidated when a contiguous chunk is free'd, they are always marked in use.