C free не работает внутри вложенных malloc и realloc - PullRequest
1 голос
/ 07 марта 2019

У меня есть следующий код:

#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;
}

Но если я скомпилировал этот код и запустил двоичный файл, я получил бы следующую ошибку:

*** 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]

Если я удаляю строку (char *buffer_ = (char*) malloc(1);) и следующую строку free(buffer_);, бинарный файл работает отлично. Если я заменю те же две строки на printf("Hello");, я получу ту же ошибку. Если я заменю char name[..] на двойное имя, это сработает, если я заменю char name[..] на long double, то снова произойдет сбой. Это очень странно для меня. Что я делаю не так?

Ответы [ 2 ]

5 голосов
/ 07 марта 2019

Если все идет хорошо, вы должны увидеть realloc как malloc, затем memcpy и free.Так, в частности, если этот realloc успешен, ваше выделение entries уже давно прошло, когда вы выполните free.

1 голос
/ 07 марта 2019

Похоже, вы предполагаете, что realloc() будет повторно использовать память, на которую указывает entries. Хотя иногда он может повторно использовать существующее распределение (особенно когда вы перераспределяете на меньший размер), так что hz == entries, это не обязательно так, и вы никогда не должны предполагать это.

Насколько вам известно, память, на которую указывает entries, была освобождена на realloc(), а единственная действительная память на которую указывает hz.

Причина сбоя при выполнении (char*) malloc(1), вероятно, заключается в том, что это выделяет память после предыдущего выделения. Без этого распределения realloc() смог увеличить исходное распределение в это пространство. Аналогичным образом, вызов printf(), вероятно, приводит к некоторому выделению внутренней памяти, что препятствует увеличению объема выделения. Другие незначительные изменения также влияют на макет памяти.

...