2012-11-01 25 views
5

Ho scritto questo pezzo innocenti di codice, e si traduce in un errore così malvagio:SIGABRT in malloc.c, cosa è successo?

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

uscita dal debug (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) 

ho controllato gli argomenti passati, anche. Loro dove proprio come dovrebbero essere:

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) 

qualcuno può immaginare, che cosa va storto qui? So che ci sono funzioni per mettere insieme due stringhe, ma voglio farlo da solo!

cordiali saluti.

+3

Sembra una perdita di dati. L'errore effettivo potrebbe essere praticamente ovunque nel tuo codice, possibilmente lontano, molto lontano da quel blocco. – Mat

+0

Libc ti ha punito per aver lanciato il valore di ritorno di 'malloc()'. –

+0

solo by-the-way: 'newalloc_size = ... + 1' per consentire la terminazione di' 0' – slashmais

risposta

7

Questo puzza come una perdita di memoria o un overflow del buffer (o qualche altro danneggiamento dell'heap) altrove nel programma. Suggerisco di ricompilarlo utilizzando le opzioni -Wall -g su gcc, per migliorare il programma fino a quando non viene fornito alcun avviso dal compilatore e per utilizzare valgrind e gdb per eseguire il debug del problema.

In realtà, la sua dichiarazione

result = (char*) malloc(newalloc_size); 

è sbagliato (mancanza di spazio per la terminazione byte null). Probabilmente si desidera

result = malloc(newalloc_size+1); 

ma si dovrebbe imparare a utilizzare asprintf

+1

'' valgrind'' è davvero il modo per andare qui. –

+0

Grazie. Lo zero-char mancante non è stato aggiunto nel codice lì sopra, ma è già nel mio codice. Appena copiato prima di aggiungere il +1! Comunque grazie! Darei un'occhiata a valgrind e asprintf. – musicmatze

3

dal codice, la risposta più probabile è che si sta utilizzando le stringhe null-terminate e non permettendo lo spazio per il nulla di terminazione nel buffer voi allocare.

Prova a modificare la linea si dispone:

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

Il nulla di terminazione è stato scritto al di fuori del buffer malloc'd, dove è probabilmente sovrascrive parte della contabilità interna di malloc. Ciò causerà il danneggiamento dell'heap, che prima o poi causerà la rottura di malloc.

-1

Stavo cercando di allocare troppa memoria e ho ottenuto anche l'errore diabolico (codice di errore: EXC_I386_INVOP).

L'ho rintracciato tramite gli strumenti di diagnosi (in XCode 6.1.1) in Prodotto/Schema/Modifica schema ... e quindi in Esegui/Diagnosi.