2014-07-11 14 views
6

Ho un programma C++ che chiama alcune routine C generate da Flex/Bison.malloc() indirizzo di ritorno a cui non posso accedere

Quando a indirizzare un 8,1 piattaforma Windows a 64 bit, mi ha colpito la seguente eccezione in fase di esecuzione:

Unhandled exception at 0x0007FFFA70F2C39 (libapp.dll) in application.exe: 0xC0000005: 
Access violation writing location 0x000000005A818118. 

ho tracciato questa eccezione al seguente pezzo di codice:

YY_BUFFER_STATE yy_create_buffer(FILE *file, int size) 
{ 
    YY_BUFFER_STATE b; 
    b = (YY_BUFFER_STATE) yy_flex_alloc(sizeof(struct yy_buffer_state)); 
    if (! b) 
     YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); 
    b->yy_buf_size = size; // This access is what throws the exception 
} 

Per riferimento , in altre parti del codice (generato anche da Flex/Bison), abbiamo:

typedef struct yy_buffer_state *YY_BUFFER_STATE; 
struct yy_buffer_state 
{ 
    FILE *yy_input_file; 
    char *yy_ch_buf; 
    char *yy_buf_pos; 
    yy_size_t yy_buf_size; 
    // ... other fields omitted, 
    // total struct size is 56 bytes 
} 

static void *yy_flex_alloc(yy_size_t size) 
{ 
    return (void *) malloc(size); 
} 

I trace d torna alla chiamata malloc e osserva che lo stesso malloc sta restituendo l'indirizzo 0x000000005A818118. Ho anche controllato errno, ma non è impostato dopo la chiamata a malloc.

La mia domanda è: perché lo malloc mi fornisce un indirizzo a cui non ho accesso e come posso farmi fornire un indirizzo corretto?

Nota: osservo questo comportamento solo in Windows 8.1 a 64 bit. Passa con altre varianti di Windows a 32 bit, oltre a Windows 7 a 32 bit.

informazioni di compilazione: Sto compilando questo su un computer Windows 8.1 computer a 64 bit utilizzando Visual Studio 2012.

Se aiuta, ecco il codice disassemblato:

// b = (YY_BUFFER_STATE) yy_flex_alloc(...) 
0007FFFA75E2C12 call yy_flex_alloc (07FFFA75E3070h) 
0007FFFA75E2C17 mov qword ptr [b],rax 
// if (! b) YY_FATAL_ERROR(...) 
0007FFFA75E2C1C cmp qword ptr [b],0 
0007FFFA75E2C22 jne yy_create_buffer+30h (07FFFA75E2C30h) 
0007FFFA75E2C24 lea rcx,[yy_chk+58h (07FFFA7646A28h)] 
0007FFFA75E2C2B call yy_fatal_error (07FFFA75E3770h) 
// b->yy_buf_size = size 
0007FFFA75E2C30 mov rax,qword ptr [b] 
0007FFFA75E2C35 mov ecx,dword ptr [size] 
0007FFFA75E2C39 mov dword ptr [rax+18h],ecx 

Grazie!

+0

ho reran questo segmento più volte, 'malloc' sia restituisce' 00000000 -------- 'o' 'FFFFFFFF -------- per l'indirizzo dello spazio "allocato". –

+0

Molto probabilmente, un'altra parte del codice, apparentemente non correlata, è riuscita a corrompere l'heap (ad esempio, eseguendo un overrunning di un buffer con allocazione heap). La parte del codice che stai guardando è una vittima innocente. –

+0

Il programma sta sperimentando lo scenario di corruzione dell'heap. Puoi riferire il post su questo articolo: http://stackoverflow.com/a/22074401/2724703 –

risposta

3

La vera risposta è:

durante la compilazione flex-generated .c sorgente in Visual Studio, non include stdlib.h (dove malloc definito come il ritorno void *) e Visual Studio richiede un po 'propria definizione, dove malloc rendimenti int. (Credo che sia per una sorta di compatibilità)

Visual Studio stampe:

'C4013 avviso: 'malloc' non definito; assumendo extern ritorno int' sizeof (int) == 4, ma i valori di indicatori su sistemi x64 spesso superano 4 byte

Così il puntatore appena tagliato alle basse 4 byte.

Sembra che questo problema venga visualizzato solo nello studio di visualizzazione x64 bit nei file .c.

Così, la soluzione sarà - è sufficiente includere stdlib.h da soli, o definire alcune macro, che porterà in sorgente di Flex-generated di includere stdlib.h.

+0

Posso solo immaginare quante ore mi hai appena salvato con questa risposta. – Rafal

2

In circostanze normali, malloc() restituirà un puntatore a memoria valida, accessibile o NULL. Quindi, i tuoi sintomi indicano che malloc() si sta comportando in un modo non specificato. Sospetto che, ad un certo punto prima, il tuo programma abbia scritto al di fuori della sua memoria valida, corrompendo così le strutture dati utilizzate internamente da malloc().

Esaminare il processo con uno strumento di analisi della memoria in fase di esecuzione dovrebbe aiutare a identificare l'origine del problema. [Vedi questo post per suggerimenti su strumenti di analisi della memoria per Windows: Is there a good Valgrind substitute for Windows?]

+0

Grazie, questo è un buon suggerimento. Lo esaminerò non appena posso installare un rilevatore di perdite compatibile con Windows 8 ... Ho fatto girare Valgrind sulla versione Linux di questa applicazione e non sembrava esserci nulla di sospetto. Nel momento in cui viene eseguita questa parte del codice, ho perso solo 4 byte (a causa di una funzione di libreria che non posso modificare ...) –