2010-06-07 17 views
54

Sto implementando un algoritmo polinomiale di divisione e conquista in modo da poterlo confrontare con un'implementazione OpenCL, ma non riesco a far funzionare malloc. Quando eseguo il programma, assegna un sacco di cose, controlla alcune cose, quindi invia l'algoritmo al numero size/2. Poi, quando mi ha colpito di nuovo la linea malloc sputa fuori questo:Perché viene visualizzato un errore di asserzione di malloc C?

malloc.c: 3096: sYSMALLOc: Asserzione `(old_top == (((mbinptr) (((char *) & ((AV) - > bidoni [((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) -> dimensione & 0x1) & & ((unsigned long) old_end & pagemask) == 0)' fallito. interrotta

La linea in questione è:

int *mult(int size, int *a, int *b) { 
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2; 
    fprintf(stdout, "size: %d\n", size); 

    out = (int *)malloc(sizeof(int) * size * 2); 
} 

ho controllato dimensioni con un fprintf, ed è un numero intero positivo (di solito 50 a questo punto). Ho provato a chiamare malloc con un numero normale e ho ancora ricevuto l'errore. Sono solo perplesso su quello che sta succedendo, e nulla da Google che ho trovato finora è utile.

Qualche idea cosa sta succedendo? Sto cercando di capire come compilare un GCC più recente nel caso si tratti di un errore del compilatore, ma ne dubito davvero.

+0

ho il sospetto che il problema sia in realtà una linea prima di quella. Forse un doppio libero? –

+0

3a linea nel programma: int * mult (int size, int * a, int * b) { \t int * fuori, i, j, * tmp1, * tmp2, * TMP3, * tmpa1 , * tmpa2, * tmpb1, * tmpb2, d, * res1, * res2; \t fprintf (stdout, "dimensione:% d \ n", dimensione); \t \t out = (int *) malloc (sizeof (int) * size * 2); – Chris

risposta

65

99,9% di probabilità di memoria che avete corrotto (sovra o sotto-scorreva un buffer, scrisse a un puntatore dopo che è stato liberato, chiamata gratuita due volte sullo stesso puntatore, ecc)

eseguire il codice sotto Valgrind per vedere dove il tuo programma ha fatto qualcosa di sbagliato.

+1

corretto. Valgrind ha sicuramente aiutato. Ho trascritto il mio vecchio codice matlab in modo errato e ho avuto un ciclo for che ha iterato su j, quindi all'interno di esso j ++ ha sovrascritto l'array su cui stava scrivendo e in qualche modo ha causato il fallimento di malloc. grazie per l'aiuto! – Chris

+0

Valgrind era lo strumento di cui avevo bisogno per capire cosa stava succedendo quando ho ricevuto questo errore. Grazie per averlo menzionato. – alexwells

+1

Ho fatto una compilazione pulita e ha funzionato correttamente. –

1

Abbiamo ottenuto questo errore perché abbiamo dimenticato di moltiplicare per sizeof (int). Notare che l'argomento di malloc (..) è un numero di byte, non un numero di parole macchina o altro.

0

stavo porting di un'applicazione da Visual C a GCC su Linux e ho avuto lo stesso problema con

malloc.c: 3096: sYSMALLOc: Asserzione usando gcc su Ubuntu 11.

Ho spostato lo stesso codice su una distribuzione Suse (su un altro computer) e non ho alcun problema.

Sospetto che i problemi non siano nei nostri programmi ma nella propria libc.

40

Per una migliore comprensione di perché si verifica, mi piacerebbe espandere la risposta di @ r-samuel-klatchko un po '.

Quando chiami malloc, ciò che sta realmente accadendo è un po 'più complicato del semplice dare un pezzo di memoria con cui giocare. Sotto il cofano, malloc conserva anche alcune informazioni sulla gestione della memoria che ha fornito (soprattutto la sua dimensione), in modo che quando si chiama free, sappia cose come la quantità di memoria da liberare. Queste informazioni vengono normalmente mantenute prima che la posizione di memoria venga restituita da malloc. Informazioni più esaustivo si possono trovare on the internet™, ma il (molto) idea di base è qualcosa di simile:

+------+-------------------------------------------------+ 
+ size |     malloc'd memory    + 
+------+-------------------------------------------------+ 
     ^-- location in pointer returned by malloc 

Basandosi su questo (e semplificando notevolmente le cose), quando si chiama malloc, ha bisogno di ottenere un puntatore alla parte successiva della memoria che è disponibile. Un modo molto semplice per farlo è guardare il precedente bit di memoria che ha dato via e spostare size byte più in basso (o in alto) nella memoria. Con questa implementazione, si finisce con la memoria cercando qualcosa di simile dopo l'attribuzione di p1, p2 e p3:

+------+----------------+------+--------------------+------+----------+ 
+ size |    | size |     | size |   + 
+------+----------------+------+--------------------+------+----------+ 
     ^- p1     ^- p2      ^- p3 

Allora, che cosa sta causando l'errore?

Bene, immagina che il tuo codice scriva erroneamente oltre la quantità di memoria che hai allocato (o perché hai allocato meno del necessario come era il tuo problema o perché stai usando le condizioni al contorno sbagliate da qualche parte nel tuo codice). Supponiamo che il tuo codice scriva così tanti dati a p2 che inizi a sovrascrivere quello che si trova nel campo size di p3. Alla successiva chiamata malloc, verrà esaminata l'ultima posizione di memoria restituita, esaminato il relativo campo delle dimensioni, spostato su p3 + size e quindi avviato l'allocazione della memoria da lì. Poiché il tuo codice ha sovrascritto size, tuttavia, questa posizione di memoria non si trova più dopo la memoria allocata in precedenza.

Inutile dire che questo può rovinare il caos! Gli implementatori di malloc hanno quindi inserito una serie di "asserzioni", o verifiche, che cercano di fare un po 'di controllo di sanità mentale per prendere questo (e altri problemi) se stanno per accadere. Nel tuo caso particolare, queste asserzioni sono violate e quindi malloc abortisce, dicendoti che il tuo codice stava per fare qualcosa che in realtà non dovrebbe fare.

Come precedentemente affermato, questa è una grossolana semplificazione, ma è sufficiente per illustrare il punto. L'implementazione glibc di malloc è più di 5k linee e ci sono state notevoli ricerche su come costruire buoni meccanismi di allocazione dinamica della memoria, quindi non è possibile coprirlo tutto in una risposta SO. Spero che questo ti abbia dato una visione di ciò che sta veramente causando il problema!

+0

Questa dovrebbe essere la risposta accettata .. –

1

ho ottenuto il seguente messaggio, simile al vostro uno:

 

    program: malloc.c:2372: 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. 

Ha fatto un errore un metodo chiamata prima, quando si utilizza malloc. Sovrascrive in modo errato il segno di moltiplicazione '*' con un '+', quando si aggiorna il fattore dopo sizeof() - l'operatore all'aggiunta di un campo a un array di car unsigned.

ecco il codice responsabile per l'errore nel mio caso:

 

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5); 
    b[INTBITS]=(some calculation); 
    b[BUFSPC]=(some calculation); 
    b[BUFOVR]=(some calculation); 
    b[BUFMEM]=(some calculation); 
    b[MATCHBITS]=(some calculation); 

In un altro metodo dopo, ho usato di nuovo malloc e ha prodotto il messaggio di errore sopra indicato. La chiamata era (abbastanza semplice):

 

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50); 

Pensate utilizzando il '+' - segno al 1 ° chiamata, che portano a mis-calcolo in combinazione con l'inizializzazione immediata della matrice dopo (memoria sovrascrivendo che non era assegnato alla matrice), ha portato un po 'di confusione nella mappa della memoria di malloc. Pertanto la seconda chiamata è andata storta.

0

ho avuto lo stesso problema, ho usato malloc over n di nuovo in loop per aggiungere nuovi dati di stringa char *. Ho affrontato lo stesso problema, ma dopo aver rilasciato il problema di memoria allocata void free() sono stati ordinati

Problemi correlati