2012-11-01 9 views
5

Napisałem ten niewinny kawałek kodu i skutkuje takim złym błędu:SIGABRT w malloc.c, co się właśnie stało?

static char * prefixed(char * pref, char *str) { 
    size_t newalloc_size = sizeof(char) * (strlen(pref) + strlen(str)); 
    char * result = (char*) malloc(newalloc_size); 
    [...] 

wyjściowy z debugowania (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) 

Sprawdziłem przekazywane argumenty, too. Są tacy, jak powinni:

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) 

Czy ktoś może sobie wyobrazić, co tu jest nie tak? Wiem, że istnieją funkcje łączenia dwóch ciągów, ale chcę to zrobić samodzielnie!

Pozdrawiamy.

+3

To wygląda na korupcję sterty. Rzeczywisty błąd może dotyczyć dowolnego miejsca w kodzie, prawdopodobnie daleko, daleko od tego bloku. – Mat

+0

Libc ukarał cię za rzucenie wartości zwracanej przez 'malloc()'. –

+0

just-the-way: 'newalloc_size = ... + 1', aby umożliwić zakończenie' 0' – slashmais

Odpowiedz

7

To pachnie jak wyciek pamięci lub przepełnienie bufora (lub inne uszkodzenie sterty) gdzie indziej w twoim programie. Proponuję przekompilować go przy użyciu opcji -Wall -g na gcc, aby ulepszyć twój program, dopóki nie zostaną podane ostrzeżenia przez kompilator, i aby użyć valgrind i gdb do debugowania problemu.

Właściwie swoją wypowiedź

result = (char*) malloc(newalloc_size); 

jest źle (brak miejsca na kończącym NUL). Prawdopodobnie chcesz

result = malloc(newalloc_size+1); 

ale trzeba nauczyć się wykorzystywać asprintf

+1

'' valgrind'' jest naprawdę sposobem, aby przejść tutaj. –

+0

Dziękuję. Brakujący znak zero nie został dodany w kodzie tam, ale jest już w moim kodzie. Po prostu skopiowane przed dodaniem +1! W każdym razie dzięki! Będę patrzył na valgrind i asprintf. – musicmatze

3

z kodu, najbardziej prawdopodobną odpowiedzią jest, że używasz ciągi zerowych zakończone i nie pozwalając miejsca na null kończącej się w buforze ty przeznaczyć.

Spróbuj to zamiast linii masz:

size_t newalloc_size = sizeof(char) * (strlen(pref) + strlen(str) + 1); 

Kończący zerowy jest napisane spoza malloc'd bufora, gdzie jest prawdopodobnie nadpisując część księgowych Malloc za. Spowoduje to uszkodzenie sterty, co prędzej czy później spowoduje pęknięcie malloc.

-1

Próbowałem przydzielić zbyt dużo pamięci i dostałem również błąd zła (kod błędu: EXC_I386_INVOP).

Śledziłem to za pomocą narzędzi diagnostycznych (w XCode 6.1.1) w Product/Scheme/Edit Scheme ..., a następnie w Run/Diagnosis.

Powiązane problemy