2010-03-18 16 views
19

Mi chiedo se esiste un buon metodo per trovare il codice sorgente che causa un errore di danneggiamento dell'heap, dato l'indirizzo di memoria dei dati scritti "all'esterno" dell'heap allocato blocco in Visual Studio;Visual Studio - come trovare l'origine degli errori di danneggiamento dell'heap

Dedicato (0008) free list elemento 26F7F670 è la dimensione sbagliata (morto)

(il tentativo di scrivere alcune note su come trovare gli errori di memoria)

Grazie in anticipo!

risposta

1

È possibile impostare un punto di interruzione su una scrittura sull'indirizzo di memoria. Il debugger mostrerà quindi il codice che scrive nella posizione, ma è ancora necessario capire quali delle scritture stanno causando il problema.

0

Sto assumendo C++ come lingua.

Se l'errore è riproducibile e l'indirizzo danneggiato è sempre lo stesso, è possibile inserire un punto di interruzione dati per interrompere il programma durante la scrittura a questo indirizzo.

+1

La lingua è mista C/C++. L'indirizzo danneggiato è diverso in ogni sessione di debug, quindi suppongo che non sia possibile utilizzare un punto di interruzione dei dati – Danne

+1

Purtroppo hai ragione. In questi casi, il mio approccio è quello di #define free/delete per essere nulla. Se il problema scompare, #define malloc/new/free/delete a una funzione che registra ogni chiamata, al fine di trovare cancellazioni o eliminazioni duplicate senza allocazione. – Timores

3

Forse si può provare Application Verifier di Microsoft. Risolve un problema simile per me una volta, attivando controlli extra sulle operazioni di heap. A mio parere, la casualità dell'indirizzo danneggiato è perché l'heap può essere "sottilmente" danneggiato e il problema non verrà visualizzato fino a quando qualcosa di grosso non accadrà all'heap (come l'allocazione massiva/gratuita).

36

cominciare con l'installazione di WinDbg:

http://www.microsoft.com/whdc/Devtools/Debugging/default.mspx

quindi accendere il pageheap come questo:

gflags.exe –p /enable yourexecutable.exe /full 

Questo inserirà una pagina non scrivibile dopo ogni allocazione heap.

Dopo questo avvio dell'eseguibile dall'interno di windbg, tutte le scritture esterne all'heap verranno catturate da questo debugger. Per attivare della pageheap poi usare questo:

gflags.exe -p /disable yourexecutable.exe 

Maggiori informazioni su come utilizzare il PageHeap here.

+3

La migliore soluzione! Salvato la mia vita. Inoltre, apre direttamente gflags.exe e utilizza anche la GUI. Vai su "File immagine", inserisci il nome del file exe e seleziona "Abilita heap di pagina". Qualsiasi debugger funzionerà. – Eliko

+1

Grazie mille. Mi ci sono voluti due giorni prima di scoprire questa tecnica. Ho appena spuntato "Abilita l'heap della pagina" e uso il debugger di Visual Studio come al solito. E poi, si romperà esattamente nella posizione del codice causando il bug di corruzione dell'heap. Il mio bug è dovuto al fatto che un thread alimenta continuamente i dati, mentre altri thread allocano solo memoria sufficiente per i vecchi dati, il che non è sufficiente per la memorizzazione di nuovi dati. – khanhhh89

+0

Sto cercando di installare questi strumenti di debug, ma mi sta chiedendo di disinstallare l'ultimo SDK. Si prega di suggerire –

2

Probabilmente è troppo tardi ma se è compilato con gcc e può essere eseguito su linux è possibile utilizzare valgrind per trovare l'origine del problema (non ricordo le bandiere, l'ho usato solo una volta con grande successo).

+0

In bocca al lupo, Microsoft ha fatto di tutto per assicurarsi che i loro comandi di elaborazione delle stringhe siano incompatibili con quanti più standard possibile. Se è molto semplice, potresti farla franca. – Owl

2

Per Windows 10 è possibile attivare la PageHeap option in the GFlags Tool, questo strumento è incluso come parte del Debugging Tools for Windows.

Le opzioni Heap di pagina in GFlags consentono di selezionare la verifica heap standard o la verifica heap a pagina intera. Attenzione, la verifica dell'heap completo utilizza una pagina intera di memoria per ogni allocazione in modo che possa causare carenze di memoria del sistema.

Per attivare la pagina heap in GFlags:

• Per abilitare standard di pagina mucchio di verifica, la versione standard scriverà un modello alla fine di ogni allocazione heap e quindi esaminare il motivo quando gli stanziamenti sono liberati .

Per verificare tutti i processi utilizzano:

gflags/r + hpa

gflags/k + hpa

per un uso singolo processo:

gflags/P/abilitare ImageFileName

• Per abilitare verifica completa pagina mucchio per un processo, questa opzione consente di inserire una pagina inaccessibile alla fine di ogni allocazione in modo che il programma si arresta immediatamente se si cerca di accessi memoria oltre l'allocazione, questo dovrebbe essere usato solo su un singolo processo a causa del consumo di memoria pesante.

gflags/i ImageFileName + hpa

gflags/p/abilitare/ImageFileName completi

I due comandi precedenti sono intercambiabili.

Nota: tutte le impostazioni dell'heap della pagina sopra menzionate sono impostazioni del sistema memorizzate nel Registro di sistema (tranne/k) e restano valide fino a quando non vengono modificate. L'impostazione/k è un'impostazione Kernel flag impostata per questa sessione e andrà persa allo spegnimento di Windows

Un altro strumento utile è lo Application Verifier, ma questo non fa parte degli strumenti di debug per Windows, ma è incluso nello Windows Software Development Kit (SDK).

0

Assicurarsi che tutte le librerie a cui si sta collegando siano compilate nella stessa versione CLR dell'applicazione in esecuzione, tutto in Versione o tutto in Debug.

Quando si compila in Debug e Release si stanno effettivamente prendendo di mira due diverse versioni della libreria di runtime C. Queste versioni sono abbastanza diverse e utilizzano strategie diverse per allocare memoria e utilizzano diversi heap. Ma la cosa più importante da sapere è che NON sono compatibili tra loro.

La libreria di runtime Release C ha allocato la memoria come previsto, mentre il Debug aggiungerà informazioni extra, come i blocchi di guardia per tracciare l'overflow del buffer e la posizione che ha chiamato la funzione di allocazione, e a sua volta assegna più memoria rispetto alla Release.

Se stai collegando la tua applicazione a un mix di DLL che sono state create in Release e Debug, molto probabilmente finirai per provare a eliminare un oggetto in un CLR che è stato creato in un altro. Ciò significa che tenterai di liberare più o meno memoria di ciò che è stato assegnato all'oggetto e questo può corrompere l'heap.

È necessario creare l'applicazione, nonché allegare alle librerie che sono costruite con la stessa configurazione, Release o Debug.

Questo problema può verificarsi in particolare nei moduli che vengono compilati con diversi compilatori.

C'è un modo per aggirare, che menzionerò ma non lo consiglio. Se per qualche motivo hai ancora bisogno di costruire in diverse modalità, questa soluzione consentirà di allocare e liberare tutta la memoria dallo stesso heap condiviso. L'API GetProcessHeap ti consentirà di accedere all'heap condiviso attraverso i diversi moduli. Utilizzando HeapAlloc & HeapFree è possibile allocare e liberare memoria nell'heap condiviso. Nota: HeapAlloc e HeapFree dovrebbero sostituire tutte le chiamate a malloc e gratuite nella propria applicazione.

+0

Compilare contro la stessa versione di una libreria di parti 3d (ad esempio OpenCV) in entrambi i miei debug e release. Per quanto ne so, ciò significa solo che nel debug non posso entrare in nessuno dei codici di party 3d e che funziona anche un po 'più veloce nel debug. Mi sbaglio, pensi? –

+0

@ILIABROUDNO Generalmente le librerie di terze parti distribuite distribuiscono una libreria di rilascio che altri possono utilizzare in modalità di rilascio o di debug. Fanno questo costruendo le loro DLL per includere la loro copia della libreria di runtime C, insieme a questo, si assicurano di non condividere risorse CRT come l'heap attraverso i limiti della libreria per assicurare che la memoria allocata dinamicamente sia deallocata sullo stesso lato del confine. In conclusione, se le librerie di terze parti che si stanno collegando per averlo fatto, non dovresti avere problemi a usarle in Release e Debug. –

+0

@ILIABROUDNO se questo è stato utile, per favore +1 :) –

Problemi correlati