Il codice di debug dovrebbe essere lasciato in posizione, sempre, o aggiunto solo durante il debug e rimosso quando il bug è stato trovato?

32

Io, per esempio, aggiungo solo il codice di debug (come le istruzioni di stampa) quando sto cercando di localizzare un bug. E una volta trovato, rimuovo il codice di debug (e aggiungo un test case che verifica specificamente quel bug). Sento che sta ingombrando il codice reale e quindi non ha posto lì a meno che non stia eseguendo il debug.

Come si fa? Lascia il codice di debug in posizione o rimuovilo quando è obsoleto (il che potrebbe essere difficile da giudicare quando lo è)?

    
posta gablin 02.01.2011 - 23:34
fonte

8 risposte

28

Le dichiarazioni di stampa di debug devono essere eliminate; tuttavia, se è necessario aggiungerli per eseguire il debug di un problema di produzione, potrebbe essere opportuno valutare se si dispone di informazioni sufficienti per l'inserimento nel framework di registrazione. Informazioni su parametri, condizioni di errore e così via potrebbero essere utili in seguito quando verrà visualizzato il bug successivo. L'uso di un buon framework di registrazione che può contenere messaggi di log di debug o di tracciamento attivati dinamicamente può essere molto utile in the wild.

    
risposta data 02.01.2011 - 23:53
fonte
15

Il codice aggiunto specificamente per il debug deve essere rimosso dal software di produzione.

La rimozione completa o l'inserimento in sezioni di compilazione condizionale (come in C / C ++ / C #) dipende da te e dallo standard di codifica.

Ci sono diversi motivi per questo:

  1. Potrebbero esserci implicazioni di sicurezza se questo codice viene eseguito o qualcuno può accedere all'output.
  2. Potrebbe rallentare l'applicazione.
  3. Potrebbe essere fonte di confusione per gli altri sviluppatori che considerano il codice (o anche te stesso) 6 mesi dopo la linea.
risposta data 02.01.2011 - 23:40
fonte
13

ChrisF e Alaric entrambi hanno punti validi; +1 per loro. Posso identificare almeno 5 diversi tipi di codice di debug che utilizzo.

  1. Utilizzo dei registri per eseguire il dump dello stato del sistema in un momento specifico.

    void function(...)
    {
        ...dump everything i know about.
    }
    
  2. Utilizzo dei log per i punti di controllo dell'esecuzione.

    void function(...)
    {
        ...got here 1
        ...got here 2
    }
    
  3. Codice che forza effettivamente una certa condizione a essere vera, ma rompe il comportamento normale. Esempio:

    • Supponiamo di avere alcuni registri relativi a un errore, ma non è possibile riprodurre il problema. Potresti provare a scrivere codice che forza determinate variabili ad avere determinati valori che corrispondono alle informazioni nel registro.
  4. Registrazione di verifica: classificherei questo come una registrazione dettagliata che può essere utilizzata per convalidare la correttezza del software che non dovrebbe essere inclusa nella produzione, ad esempio la convalida dei singoli passaggi di un algoritmo, ad esempio.

  5. Registrazione operazioni - fare riferimento a post di Alaric . Questo è più o meno quello che intendo per "operazione di registrazione".

1, 2 e 3 dovrebbero essere eliminati completamente. Qualcosa come 4 che probabilmente compilerei condizionatamente dal codice. Per 5, Alaric ha avuto un grande vantaggio nell'essere in grado di disattivare dinamicamente i registri. Ciò può riguardare Il punto di ChrisF nel suo secondo proiettile per la maggior parte dei casi.

    
risposta data 03.01.2011 - 02:23
fonte
3

Dipende da cosa sta facendo il codice. Alcuni codici usati per il debug possono essere lasciati così com'è e alcuni dovrebbero essere rimossi.

Il codice che verifica la correttezza dei parametri in un metodo non è sempre utile una volta che il codice funziona correttamente, ma spesso viene mantenuto per assicurarsi che il codice continui a funzionare correttamente.

A volte si scrive codice in modo diverso per facilitare il debug del codice, ad esempio calcolare un valore e inserirlo in una variabile locale, quindi utilizzare la variabile nella riga successiva, che facilita il controllo del risultato del calcolo quando si passa da un codice all'altro. È possibile riscrivere il codice per utilizzare direttamente il valore calcolato, ma il costo dell'utilizzo della variabile locale è così piccolo (se non del tutto) che vi sono pochi motivi per riscrivere il codice. Inoltre, c'è un punto nel lasciare il codice invariato una volta che lo hai testato, c'è sempre un piccolo rischio di introdurre un bug quando lo si cambia.

Il codice che aggiungi solo per rintracciare un bug specifico può spesso essere rimosso dopo aver trovato il bug.

    
risposta data 03.01.2011 - 01:38
fonte
2

C'era una volta che usavo un sacco di codice di debug. Stavo quasi interamente indirizzando Windows, quindi c'era una grande quantità di questa funzione di debug delle stringhe che non ricordo più come si scrive, quindi potrei catturare la traccia con un particolare programma.

Alcuni codici di debug sono rimasti sul posto, roba particolare intesa a fornire l'annidamento delle chiamate. Tuttavia, anche se la stringa di debug per la maggior parte non sarebbe visibile su un sistema di produzione, era ancora tutto fatto con la compilazione condizionale.

La realtà è, tuttavia, che tutto quel codice di debug è stato un grande sforzo per qualcosa che è idealmente gestito in un modo diverso - usando, ovviamente, un debugger. All'epoca, non ero molto colpito dal debugger di Borland C ++. Gli strumenti erano presenti, ma troppo spesso davano risultati fuorvianti e l'uso del debugger non IDE (spesso necessario) significava memorizzare i tasti di scelta rapida, il che significava una distrazione dal lavoro in corso.

L'unica esperienza di debug che ho trovato è peggio di GDB da riga di comando.

Essere un esperto con gli strumenti che usi ogni giorno è, ovviamente, importante - ma il debugging in realtà non dovrebbe essere qualcosa che fai ogni giorno. Se usi spesso il debugger, stai bene imparando dozzine di comandi e / o scorciatoie da tastiera, a me sembra un po 'di bandiera rossa.

Quando lavoravo in Visual Studio 7, tuttavia, era chiaro che il debugging poteva essere molto pratico ed efficace. Se è possibile eseguire il debug in Visual Studio (incluse le versioni Express), il debug è un gioco da ragazzi. Non c'è dubbio che se riesci a trovare il giusto front-end GUI / IDE, GDB è anche facile ed efficace, anche se non ho ancora fatto quella ricerca.

C'è anche qualcosa da dire per i test unitari, con l'analisi della copertura usando gcov. Più sei sicuro del comportamento delle tue librerie, meno profondo sarà il tuo debugging, e meno spesso hai bisogno del debugger in primo luogo. E scrivere test di unità è una cosa abbastanza ragionevole che dovresti fare quasi tutti i giorni.

Tool inaspettatamente importante = cmake, uno strumento di compilazione che mi consente di passare facilmente da un edificio all'altro per GCC e per VC ++, tra le altre cose. Quindi posso fare il mio test unitario e la copertura basata su gcov usando GCC, ma facilmente passare a VC ++ per usare il debugger.

    
risposta data 03.01.2011 - 02:06
fonte
2

La mia opinione su di esso: il codice di debug utilizzato per uccidere un bug all'interno del codice in questione generalmente rimuovo del tutto. Il codice di debug utilizzato per uccidere un bug derivante da forze esterne generalmente commenta semplicemente.

    
risposta data 03.01.2011 - 06:14
fonte
0

Se il bug proviene dal test dell'unità o dall'interno, il codice di debug potrebbe essere rimosso del tutto. Ma se il bug proviene dalla produzione, il codice di debug dovrebbe trovarsi meglio all'interno dei tag di compilazione. Inserirlo all'interno dei tag di compilazione aiuterà gli altri sviluppatori a capire che questo codice è solo a scopo di debug.

    
risposta data 03.01.2011 - 07:01
fonte
0

Utilizza TDD , quindi il tuo codice di prova ha sempre un luogo in cui è persino mantenuto.

    
risposta data 03.01.2011 - 16:38
fonte

Leggi altre domande sui tag