SIGABRT в malloc.c, что только что произошло?
Я написал этот невинный кусок кода, и он приводит к такой злой ошибке:
static char * prefixed( char * pref, char *str ) {
size_t newalloc_size = sizeof(char) * (strlen(pref) + strlen(str));
char * result = (char*) malloc( newalloc_size );
[...]
вывод отладки (cgdb):
Breakpoint 1, prefixed (pref=0x401345 "Env: ", str=0x4012b5 "Home") at ./src/backend/os/env.c:77
(gdb) s
(gdb) p newalloc_size
$1 = 9
(gdb) s
envtest: malloc.c:2368: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >=
(unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)'
failed.
Program received signal SIGABRT, Aborted.
0x00007ffff7a68fd5 in raise () from /usr/lib/libc.so.6
(gdb)
Я также проверил переданные аргументы. Они там, где они должны быть:
Breakpoint 1, prefixed (pref=0x401345 "Env: ", str=0x4012b5 "Home") at ./src/backend/os/env.c:77
(gdb) p pref
$2 = 0x401345 "Env: "
(gdb) p strlen(pref)
$3 = 5
(gdb) p str
$4 = 0x4012b5 "Home"
(gdb) p strlen(str)
$5 = 4
(gdb)
Кто-нибудь может представить, что здесь идет не так? Я знаю, что есть функции для объединения двух строк, но я хочу сделать это самостоятельно!
С уважением.
3 ответа
Это пахнет как утечка памяти или переполнение буфера (или какое-либо другое повреждение кучи) в других местах вашей программы. Я предлагаю перекомпилировать его, используя -Wall -g
варианты gcc
, чтобы улучшить вашу программу до тех пор, пока компилятор не выдаст никаких предупреждений, и использовать valgrind и gdb
отладить проблему.
Собственно, ваше заявление
result = (char*) malloc( newalloc_size );
неправильно (не хватает места для завершающего нулевого байта). Вы, вероятно, хотите
result = malloc(newalloc_size+1);
но вы должны научиться использовать asprintf
Из вашего кода наиболее вероятный ответ заключается в том, что вы используете строки с нулевым символом в конце и не допускаете места для завершающего нулевого значения в буфере, который вы выделяете.
Попробуйте это вместо той строки, которая у вас есть:
size_t newalloc_size = sizeof(char) * (strlen(pref) + strlen(str) + 1);
Завершающий ноль записывается вне вашего буфера malloc, где он, вероятно, перезаписывает часть внутренней бухгалтерии malloc. Это приведет к повреждению кучи, что рано или поздно приведет к поломке malloc.
Я пытался выделить слишком много памяти и тоже получил злую ошибку (код ошибки: EXC_I386_INVOP).
Я выследил его с помощью инструментов диагностики (в XCode 6.1.1) в Product/Scheme/Edit Scheme... и затем в Run/Diagnosis.