Domanda

Quali sono i motivi tipici per gli insetti e il comportamento del programma anomalo che si manifestano solo in modalità di compilazione di rilascio, ma che non si verificano quando in modalità debug?

È stato utile?

Soluzione

Molte volte, in modalità debug in C ++ tutte le variabili vengono inizializzate nulli, mentre lo stesso non avviene in modalità di rilascio a meno che non espressamente indicato.

Controlla tutte le macro di debug e le variabili non inizializzate

Il tuo programma utilizza threading, quindi l'ottimizzazione può anche causare alcuni problemi nella modalità di rilascio.

Controllare anche per tutte le eccezioni, ad esempio, non direttamente legati alla modalità di rilascio, ma a volte abbiamo semplicemente ignorare alcune eccezioni critiche, come violazione di accesso mem in VC ++, ma lo stesso può essere un problema, almeno in altri sistemi operativi come Linux, Solaris. Idealmente il vostro programma non dovrebbe prendere tali eccezioni critiche come l'accesso a un puntatore NULL.

Altri suggerimenti

Un errore comune utilizza un'espressione con effetto collaterale all'interno di un ASSERT.

Altre differenze potrebbero essere:

  • In un linguaggio di garbage collection, il collettore è di solito più aggressivo nella modalità di rilascio;
  • Layout di memoria può spesso essere diverso;
  • Memoria può essere inizializzato in modo diverso (ad esempio, potrebbe essere azzerato in modalità debug, o ri-usato più aggressivamente nel rilascio);
  • Gli abitanti del posto may essere promosso a registrare valori in uscita, che può causare problemi con virgola mobile valori.

Sono stato morso da una serie di bug in passato che sono stati bene in build di debug, ma accelerato di build di rilascio. Ci sono molte cause sottostanti (compresi ovviamente quelli che sono già stati riassunti in questa discussione) e sono stato catturati da tutti i seguenti:

  • Le variabili membro o funzioni membro in un #ifdef _DEBUG, in modo che una classe è una dimensione diversa in una build di debug. A volte #ifndef NDEBUG viene utilizzato in una build di rilascio
  • Similmente, c'è un #ifdef diverso che sembra essere presente solo in una delle due build
  • La versione di debug utilizza versioni di debug delle librerie di sistema, in particolare le funzioni di heap e di allocazione di memoria
  • funzioni inline in un build di rilascio
  • Ordine di inclusione di file di intestazione. Questo non dovrebbe causare problemi, ma se avete qualcosa come un #pragma pack che non è stato reimpostare allora questo può portare a problemi di brutto. Problemi simili possono verificarsi anche utilizzando le intestazioni precompilate e costretto include
  • Cache: si può avere codice come cache che solo si abitua in build di rilascio, o limiti di dimensione della cache che sono diversi
  • configurazioni di progetto: le configurazioni di debug e di rilascio potrebbero avere diverse impostazioni di generazione (questo è probabile che accada quando si utilizza un IDE)
  • Condizioni di gara, problemi di tempistica e Vari gli effetti collaterali che si verificano a seguito di debug solo codice

Alcuni suggerimenti che ho accumulato nel corso degli anni per andare a fondo di Debug / bachi release:

  • Provare a riprodurre comportamenti anomali in una build di debug, se è possibile, e anche meglio, dare una prova di unità di catturarlo
  • Pensate a quello che differisce tra i due: impostazioni del compilatore, cache, eseguire il debug di solo codice. Cercare di minimizzare temporaneamente queste differenze
  • Crea una build di rilascio con ottimizzazioni spento (così è molto più probabile per ottenere dati utili nel debugger), o un build di debug ottimizzato. Riducendo al minimo i cambiamenti tra il debug e rilascio, è molto più probabile che sia in grado di isolare, che differenza sta causando il bug.

Sì !, se avete la compilazione condizionale, ci possono essere errori (ottimizzato codice di rilascio versi, non ottimizzato codice di debug), memoria riutilizzo contro il debug mucchio di temporizzazione.

E 'possibile, soprattutto se si è nel regno C.

Una causa potrebbe essere che la versione di debug possono aggiungere il codice per verificare la presenza di puntatori randagi e in qualche modo protegge il codice da crash (o comportarsi in modo non corretto). Se questo è il caso si dovrebbe controllare attentamente le avvertenze e gli altri messaggi si ottiene dal vostro compilatore.

Un'altra causa potrebbe essere l'ottimizzazione (che è normalmente per le versioni di rilascio e fuori per il debug). Il layout codice ei dati possono essere stati ottimizzati e mentre il programma di debug solo è stato, ad esempio, l'accesso a memoria inutilizzata, la versione è ora cercando di accedere alla memoria riservata o anche indicando codice!

EDIT: Vedo altri menzionato: naturalmente si potrebbe avere sezioni intere di codice che sono condizionalmente esclusi se non la compilazione in modalità debug. Se questo è il caso, mi auguro che sia davvero il codice di debug e non qualcosa di vitale per la correttezza del programma stesso!

Le funzioni di libreria CRT si comportano diversamente in di debug vs rilascio (/ MD vs / MDD).

Per esempio, le versioni di debug spesso precompilare i buffer si passa alla lunghezza indicata per verificare il vostro reclamo. Gli esempi includono strcpy_s, StringCchCopy, ecc Anche se le stringhe terminano in precedenza, il tuo szDest essere migliore n byte a lungo!

Certo, per esempio, se si utilizza le costruzioni come

#if DEBUG

//some code

#endif

In .NET, anche se non si utilizza la compilazione condizionale come #if DEBUG, il compilatore è ancora molto più liberale con ottimizzazioni in modalità di rilascio di quello che è in modalità di debug, che può portare a rilasciare solo i bug pure.

Avresti bisogno di dare molte più informazioni, ma sì, è possibile. Dipende che cosa la vostra versione di debug fa. Si può anche avere controlli supplementari che che non vengono compilati in un versione di registrazione o. Questi percorsi di codice solo eseguire il debug possono avere effetti collaterali indesiderati che cambiano stato o influenzano le variabili in modo strano. Build di debug di solito eseguita più lentamente, quindi questo potrebbe influenzare le condizioni di gara threading e nascondere. Lo stesso vale per le ottimizzazioni dritto in avanti da una compilazione di rilascio, è possibile (anche se improbabile in questi giorni) che una compilazione di rilascio potrebbero cortocircuitare qualcosa come un'ottimizzazione.

Senza ulteriori dettagli, voglio supporre che "non OK" significa che esso sia non viene compilato o lanci una sorta di errore in fase di esecuzione. Controllare se si dispone di codice che si basa sulla versione di compilazione, sia attraverso dichiarazioni #if DEBUG o attraverso metodi marcati con l'attributo Conditional.

Questo è possibile, se si dispone di compilazione condizionale in modo che il codice di debug e rilascio del codice sono diversi, e c'è un bug nel codice che si usa solo in modalità di rilascio.

Oltre a questo, non è possibile. Ci sono differenze nel modo in cui il codice di debug e il codice di rilascio vengono compilati, e le differenze nel modo in cui viene eseguito il codice se eseguito in un debugger o no, ma se uno qualsiasi di queste differenze causano altro che una differenza di prestazioni, il problema era lì tutti insieme.

Nella versione di debug l'errore non può essere verificando (perché l'allocazione di temporizzazione o di memoria è diverso), ma questo non significa che l'errore non c'è. Ci possono essere anche altri fattori che non sono correlati alla modalità di debug che cambia la temporizzazione del codice, causando l'errore si verifichi o meno, ma tutto si riduce al fatto che se il codice è stato corretto, l'errore non si verifica in nessuna delle situazioni.

Quindi, no, la versione di debug non è OK solo perché è possibile eseguire senza ottenere un errore. Se si verifica un errore quando lo si esegue nella modalità di rilascio, non è a causa della modalità di rilascio, è perché l'errore è stato lì fin dall'inizio.

Ci sono ottimizzazioni del compilatore che può rompere codice valido , perché sono troppo aggressivi.

Provare a compilare il codice con meno ottimizzazione abilitata.

In una funzione non-vuoto, tutti i percorsi di esecuzione dovrebbero terminare con un'istruzione di ritorno.

In modalità di debug, se si dimentica di terminare tale percorso con una dichiarazione di ritorno, la funzione di solito restituisce 0 per impostazione predefinita.

Tuttavia, nella modalità di rilascio vostra funzione può restituire i valori della spazzatura, che possono interessare quanto il programma viene eseguito.

E 'possibile. Se accade e non la compilazione condizionale è coinvolto, che si può essere abbastanza sicuri che il vostro programma è sbagliato, e sta lavorando in modalità debug solo a causa della inizializzazioni memoria fortuite o addirittura layout in memoria!

Ho appena sperimentato che, quando mi stava chiamando una funzione di montaggio che non ha ripristinato i valori precedenti dei registri.

Nella configurazione "Release", VS è stata la compilazione con / O2 che ottimizza il codice per la velocità. Così alcune variabili locali, dove solo di mapping per registri della CPU (per l'ottimizzazione), che sono stati condivisi con la funzione di cui sopra che porta a gravi casi di corruzione della memoria.

In ogni caso se non si è indirettamente scherzi con registri della CPU qualsiasi punto del codice.

Mi ricordo che tempo fa, quando stavamo costruendo DLL e PDB in C / C ++.

Mi ricordo questo:

  • L'aggiunta di dati di log avrebbe qualche volta fare la mossa bug o scomparire o fare viene visualizzato un totalmente altro errore (quindi non era davvero un'opzione).
  • Molti di questi errori in cui a causa di Char assegnazione in strcpy e strcat e array di char [] ecc ...
  • Abbiamo eliminati alcuni fuori eseguendo limiti checker e semplicemente che fissa il problemi alloc / dealloc memoria.
  • Molte volte, siamo andati sistematicamente attraverso il codice e fissati un'allocazione char (come in tutti i file).
  • Sicuramente è qualcosa legato alla allocazione di memoria e di gestione e dei vincoli e le differenze tra la modalità debug e modalità di rilascio.

E poi sperare per il meglio.

A volte, temporaneamente consegnato versioni di debug di DLL ai clienti, al fine di non tenere a bada la produzione, mentre si lavora su questi bug.

Un altro ragioni potrebbero essere chiamate DB. Sei risparmio e l'aggiornamento stesso record più volte nella stessa discussione, a volte per l'aggiornamento. E 'possibile l'aggiornamento non è riuscito o non ha funzionato come previsto perché il comando precedente creare era ancora in fase di elaborazione e per l'aggiornamento, la chiamata db non è riuscito a trovare alcun record. questo accada abituato a eseguire il debug come debugger fa in modo di completare tutte le attività in sospeso prima di atterrare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top