Reputation: 380
I have the following code:
#include <stdlib.h>
#define STRING_LENGTH 50
typedef struct entry {
char name[STRING_LENGTH];
} datum;
int main(void) {
datum *entries = NULL;
entries = (datum*) malloc(sizeof(datum)) ;
char *buffer_ = (char*) malloc(1);
free(buffer_);
void *hz = realloc(entries , 2 * sizeof(datum));
free(entries);
return 0;
}
But if I compile this code and run the binary I get the following error:
*** Error in `./a.out': double free or corruption (fasttop): 0x00005572b0381010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bfb)[0x7ff4b3842bfb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76fc6)[0x7ff4b3848fc6]
/lib/x86_64-linux-gnu/libc.so.6(+0x7780e)[0x7ff4b384980e]
./a.out(+0x799)[0x5572af4ca799]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7ff4b37f22e1]
./a.out(+0x63a)[0x5572af4ca63a]
======= Memory map: ========
5572af4ca000-5572af4cb000 r-xp 00000000 00:29 13267238517 a.out
5572af6ca000-5572af6cb000 r--p 00000000 00:29 13267238517 a.out
5572af6cb000-5572af6cc000 rw-p 00001000 00:29 13267238517 a.out
5572b0381000-5572b03a2000 rw-p 00000000 00:00 0 [heap]
7ff4ac000000-7ff4ac021000 rw-p 00000000 00:00 0
7ff4ac021000-7ff4b0000000 ---p 00000000 00:00 0
7ff4b35bb000-7ff4b35d1000 r-xp 00000000 08:01 6815758 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff4b35d1000-7ff4b37d0000 ---p 00016000 08:01 6815758 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff4b37d0000-7ff4b37d1000 r--p 00015000 08:01 6815758 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff4b37d1000-7ff4b37d2000 rw-p 00016000 08:01 6815758 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ff4b37d2000-7ff4b3967000 r-xp 00000000 08:01 6816376 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4b3967000-7ff4b3b67000 ---p 00195000 08:01 6816376 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4b3b67000-7ff4b3b6b000 r--p 00195000 08:01 6816376 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4b3b6b000-7ff4b3b6d000 rw-p 00199000 08:01 6816376 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4b3b6d000-7ff4b3b71000 rw-p 00000000 00:00 0
7ff4b3b71000-7ff4b3b94000 r-xp 00000000 08:01 6816210 /lib/x86_64-linux-gnu/ld-2.24.so
7ff4b3d6a000-7ff4b3d6c000 rw-p 00000000 00:00 0
7ff4b3d93000-7ff4b3d94000 rw-p 00000000 00:00 0
7ff4b3d94000-7ff4b3d95000 r--p 00023000 08:01 6816210 /lib/x86_64-linux-gnu/ld-2.24.so
7ff4b3d95000-7ff4b3d96000 rw-p 00024000 08:01 6816210 /lib/x86_64-linux-gnu/ld-2.24.so
7ff4b3d96000-7ff4b3d97000 rw-p 00000000 00:00 0
7ffd1bf9f000-7ffd1bfc0000 rw-p 00000000 00:00 0 [stack]
7ffd1bfdd000-7ffd1bfdf000 r--p 00000000 00:00 0 [vvar]
7ffd1bfdf000-7ffd1bfe1000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
If I delete the line (char *buffer_ = (char*) malloc(1);
) and the next line free(buffer_);
the binary works perfectly. If I replace the same two lines with an printf("Hello");
I get the same error. If I replace char name[..]
with double name it works, if I replace char name[..]
with long double
again it fails. This is very strange for me. What I am doing wrong?
Upvotes: 1
Views: 102
Reputation: 782025
You seem to be assuming that realloc()
will reuse the memory that entries
points to. While it's sometimes able reuse an existing allocation (particularly when you're reallocating to a smaller size), so that hz == entries
, this is not necessarily the case, and you should never assume it.
As far as you're concerned, the memory pointed to by entries
has been freed by realloc()
, and the only valid memory is pointed to by hz
.
The reason it fails when you do (char*) malloc(1)
is probably because that allocates the memory after the previous allocation. Without that allocation, realloc()
was able to grow the original allocation into that space. Similarly, calling printf()
probably does some internal memory allocations, which prevents it from growing the allocation. Other minor changes also affect memory layout.
Upvotes: 1
Reputation: 78953
If all goes well, you should see realloc
as a malloc
, followed by a memcpy
, followed by a free
. So in particular if that realloc
succeeds, your entries
allocation is long gone when you do the free
.
Upvotes: 5