Come ci si avvicina bug intermittenti?

voti
31

Scenario

Hai diversi bug report che mostrano tutto lo stesso problema. Sono tutti criptico con storie simili di quanto si è verificato il problema. Si seguono i passi, ma non riproduce in modo affidabile il problema. Dopo alcune indagini e ricerca web, si sospetta che quello che potrebbe essere in corso e si sono abbastanza sicuro che si può risolvere il problema.

Problema

Purtroppo, senza un modo affidabile per riprodurre il problema originale, non è possibile verificare che in realtà risolve il problema, piuttosto che avere alcun effetto o esacerbare e mascherare il vero problema. Non si poteva solo risolvere il problema fino a quando diventa riproducibili ogni volta, ma è un grosso bug e non risolverlo causerebbe agli utenti un sacco di altri problemi.

Domanda

Come si fa a verificare la modifica?

Penso che questo sia uno scenario molto familiare a chiunque abbia progettato il software, quindi sono sicuro che ci sono una pletora di approcci e migliori pratiche per affrontare i bug come questo. Attualmente stiamo cercando in uno di questi problemi sul nostro progetto in cui ho trascorso un po 'di tempo per determinare il problema, ma sono stati in grado di confermare i miei sospetti. Un collega è ammollo-test il mio fix nella speranza che un giorno di esecuzione senza un crash equivale a è risolto. Tuttavia, preferisco un approccio più affidabile e ho pensato che c'è una ricchezza di esperienza qui su SO.

È pubblicato 09/12/2008 alle 15:31
fonte dall'utente
In altre lingue...                            


18 risposte

voti
12

Bug che sono difficili da riprodurre sono quello più difficili da risolvere. Che cosa è necessario fare in modo che hai trovato la radice del problema, anche se il problema non può essere riprodotto con successo.

I bug intermittenti più comuni sono causati da race-condizioni - eliminando la corsa, o la garanzia che una parte vince sempre aver eliminato la radice del problema, anche se non si può con successo confermarla verificare i risultati. L'unica cosa che si può verificare è che la causa ha bisogno ripete.

A volte fissare ciò che è visto come la radice risolve effettivamente un problema, ma non quella giusta - non c'è evitarlo. Il modo migliore per evitare errori intermittenti è stare attenti e metodico con il design e l'architettura del sistema.

Risposto il 09/12/2008 a 15:40
fonte dall'utente

voti
7

Non sarai mai in grado di verificare la correzione senza identificare la causa principale e fino a venire con un modo affidabile per riprodurre il bug.

Per identificare la causa principale: Se la piattaforma permette, agganciare debugging post mortem nel problema.

Ad esempio, in Windows, ottenere il codice per creare un file minidump (core dump su Unix) quando incontra questo problema. È quindi possibile ottenere il cliente (o Winqual, su Windows) per l'invio di questo file. Questo dovrebbe dare ulteriori informazioni su come il codice è andato storto sul sistema di produzione.

Ma senza questo, avrete ancora bisogno di trovare un modo affidabile per riprodurre il bug. In caso contrario, non sarete mai in grado di verificare che sia risolto.

Anche con tutte queste informazioni, si potrebbe finire per la fissazione di un bug che sembra, ma non è, quello che il cliente sta vedendo.

Risposto il 09/12/2008 a 15:40
fonte dall'utente

voti
5

Io uso quello che io chiamo "stile pesante di programmazione difensiva" : aggiungo afferma in tutti i moduli che sembra collegati dal problema. Quello che voglio dire è, aggiungere un sacco di afferma , afferma evidenze, affermare stato degli oggetti in tutte le loro memebers, affermare stato "environnement", etc.

Afferma aiutano a identificare il codice che non è legata al problema.

Il più delle volte trovo l'origine del problema semplicemente scrivendo le affermazioni in quanto costringe a rileggere tutto il codice e plundge sotto le viscere della domanda per capirlo.

Risposto il 09/12/2008 a 15:47
fonte dall'utente

voti
5

Strumento della costruzione con più ampie (possibilmente opzionale) la registrazione e salvataggio dei dati che permette la riproduzione esatta della variabile UI passi gli utenti hanno preso prima che si è verificato l'incidente.

Se i dati non consente di riprodurre in modo affidabile il problema, allora avete limitato la classe di bug. Tempo di guardare le fonti di comportamento casuale, come le variazioni nella configurazione del sistema, il confronto puntatore, dati non inizializzati, ecc

A volte si "sa" (o meglio, sentire) che è possibile risolvere il problema senza test approfonditi e test di unità impalcature, perché si capisce veramente il problema. Tuttavia, se non lo fai, molto spesso si riduce a qualcosa del tipo "abbiamo corso è 100 volte e l'errore non si è verificato, quindi dovremo considerarlo risolto fino a quando la prossima volta che viene segnalato.".

Risposto il 09/12/2008 a 15:39
fonte dall'utente

voti
4

Non c'è una risposta a questo problema. A volte la soluzione che hai trovato aiuta a capire lo scenario per riprodurre il problema, nel qual caso è possibile verificare questo scenario, prima e dopo la correzione. A volte, però, che la soluzione avete trovato risolve uno solo dei problemi, ma non tutti, o come si dice maschere un problema più profondo. Vorrei poter dire "fare questo, funziona ogni volta", ma non c'è un "presente" che si inserisce quello scenario.

Risposto il 09/12/2008 a 15:39
fonte dall'utente

voti
2

Lei dice in un commento che si pensa che è una condizione di competizione. Se si pensa di sapere cosa "feature" del codice sta generando la condizione, è possibile scrivere un test per cercare di forzarlo.

Ecco il codice rischioso in c:

const int NITER = 1000;
int thread_unsafe_count = 0;
int thread_unsafe_tracker = 0;

void* thread_unsafe_plus(void *a){
  int i, local;
  thread_unsafe_tracker++;
  for (i=0; i<NITER; i++){
    local = thread_unsafe_count;
    local++;
    thread_unsafe_count+=local;
  };
}
void* thread_unsafe_minus(void *a){
  int i, local;
  thread_unsafe_tracker--;
  for (i=0; i<NITER; i++){
    local = thread_unsafe_count;
    local--;
    thread_unsafe_count+=local;
  };
}

che posso testare (in un enironment pthreads) con:

pthread_t th1, th2;
pthread_create(&th1,NULL,&thread_unsafe_plus,NULL);
pthread_create(&th2,NULL,&thread_unsafe_minus,NULL);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
if (thread_unsafe_count != 0) {
  printf("Ah ha!\n");
}

Nella vita reale, probabilmente dovrete per avvolgere il codice sospetto in qualche modo per aiutare la razza ha colpito più aver visto spesso.

Se funziona, regolare il numero di thread e altri parametri per rendere ha colpito la maggior parte del tempo, e ora si ha la possibilità.

Risposto il 09/12/2008 a 18:24
fonte dall'utente

voti
2

In primo luogo è necessario ottenere tracce dello stack dai vostri clienti, in questo modo si può effettivamente fare alcuni forense.

Avanti fare test fuzz con l'input casuale, e mantenere questi test in esecuzione per lunghi tratti, sono grandi a trovare quei casi di confine irrazionali, che i programmatori umani e tester possono trovare attraverso i casi d'uso e la comprensione del codice.

Risposto il 09/12/2008 a 15:48
fonte dall'utente

voti
1

Ho incontrato bug sui sistemi che sembrano provocare costantemente errori, ma quando si passa attraverso il codice in un debugger il problema scompare misteriosamente. In tutti questi casi, il problema è stato uno dei tempi.

Quando il sistema è in esecuzione normalmente ci fosse una sorta di conflitti per le risorse o prendendo il passo successivo prima che l'ultimo finito. Quando ho fatto un passo attraverso di essa nel debugger, le cose si stavano muovendo abbastanza lentamente che il problema è scomparso.

Una volta ho capito che era un problema di temporizzazione è stato facile trovare una soluzione. Non sono sicuro se questo è applicabile nella vostra situazione, ma ogni volta che gli insetti scompaiono nel debugger problemi di temporizzazione sono i miei primi sospetti.

Risposto il 09/12/2008 a 18:32
fonte dall'utente

voti
1

Per un errore di difficile da riprodurre, il primo passo è di solito la documentazione. Nella zona del codice che sta fallendo, modificare il codice per essere iper-esplicito: un comando per riga; pesante, gestione delle eccezioni differenziato; verbose, output di debug anche prolisso. In questo modo, anche se non è possibile riprodurre o correggere l'errore, è possibile ottenere molte più informazioni sulla causa la prossima volta che il guasto è visto.

Il secondo passo è di solito affermazione di ipotesi e limiti di controllo. Tutto quello che pensa di conoscere il codice in questione, scrivere .Asserts e controlli. In particolare, controllare gli oggetti di nullità e (se la lingua è dinamico) esistenza.

In terzo luogo, controllare la copertura unit test. I vostri test di unità in realtà coprono ogni forcella in esecuzione? Se non si dispone di test di unità, questo è probabilmente un buon punto di partenza.

Il problema con gli errori non riproducibili è che sono irriproducibile solo per lo sviluppatore. Se gli utenti finali insistono su di essi riproduce, è uno strumento prezioso per sfruttare l'incidente nel campo.

Risposto il 09/12/2008 a 18:19
fonte dall'utente

voti
1

scenario specifico

Mentre io non voglio concentrarmi solo sul problema che sto avendo, ecco alcuni dettagli della questione attuale che abbiamo di fronte e come ho affrontato finora.

Il problema si verifica quando l'utente interagisce con l'interfaccia utente (un TabControl per essere esatti) ad una particolare fase di un processo. Non si verifica sempre e credo che questo sia perché la finestra di tempo per il problema da esporre è piccolo. Il mio sospetto è che l'inizializzazione di un controllo utente (siamo in NET, utilizzando C #) coincide con un evento di cambio di stato da un'altra area dell'applicazione, che porta ad un font essendo disposto. Nel frattempo, un altro controllo (un'etichetta) cerca di trarre la sua stringa con quel carattere, e quindi l'incidente.

Tuttavia, in realtà, a conferma ciò che porta al fonte essendo disposto è rivelato difficile. La correzione attuale è di clonare il carattere in modo che l'etichetta disegno ha ancora un carattere valido, ma questo in realtà maschera il problema principale che è il carattere essendo disposto in primo luogo. Ovviamente, mi piacerebbe rintracciare la sequenza completa, ma che si sta rivelando molto difficile e il tempo è breve.

Approccio

Il mio approccio è stato il primo a guardare la traccia dello stack dalle nostre segnalazioni di crash ed esaminare il codice di Microsoft utilizzando Reflector. Purtroppo, questo ha portato ad un GDI + chiamare con poca documentazione, che restituisce solo un numero per l'errore - .NET trasforma questo in un messaggio abbastanza inutile indicare qualcosa non è valido. Grande.

Da lì, sono andato a guardare a ciò che chiamata nel nostro codice porta a questo problema. Lo stack inizia con un ciclo di messaggi, non è nel nostro codice, ma ho trovato una chiamata a Update () nella zona generale sotto sospetto e, utilizzando strumentazione (tracce, ecc), siamo stati in grado di confermare a circa il 75% di certezza che questo era la fonte del messaggio di disegno. Tuttavia, non era la fonte del bug - che chiede l'etichetta di dipingere non è un crimine.

Da lì, ho guardato ogni aspetto della chiamata vernice che stava crollando (DrawString) per vedere quello che potrebbe essere valido e cominciato a escludere ogni uno fuori fino a che cadde sui prodotti usa e getta. Ho poi determinato quali abbiamo avuto il controllo sulla e il tipo di carattere è stato l'unico. Così, ho preso uno sguardo a come abbiamo gestito il tipo di carattere e in quali circostanze Siamo disposti per identificare eventuali cause alla radice. Sono stato in grado di venire con una sequenza plausibile di eventi che si adattano alle segnalazioni da parte degli utenti, e quindi in grado di codificare una correzione a basso rischio.

Naturalmente, è passato per la mente che il bug è stato nel quadro, ma mi piace pensare che abbiamo avvitato prima di passare la colpa a Microsoft.

Conclusione

Quindi, è così che mi sono avvicinato un esempio particolare di questo tipo di problema. Come si può vedere, è tutt'altro che ideale, ma si adatta con quello che molti hanno detto.

Risposto il 09/12/2008 a 16:21
fonte dall'utente

voti
1

Questi sono orribili e quasi sempre resistente agli 'fissa' il tecnico pensa sta mettendo in, in quanto hanno l'abitudine di tornare a mordere mesi più tardi. Diffidare di eventuali correzioni apportate al bug intermittenti. Essere preparati per un po 'di lavoro sporco e la registrazione ad alta intensità come questo suona più di un problema di prova che un problema di sviluppo.

Il mio problema quando gli insetti superando come questi era che ero spesso troppo vicino al problema, non è in piedi indietro e guardare il quadro più ampio. Cercare di ottenere qualcun altro a guardare come si avvicina il problema.

In particolare il mio errore è stato quello di fare con l'impostazione di timeout e vari altri numeri magici che, a posteriori, dove borderline e così lavorato quasi tutto il tempo. Il trucco nel mio caso è stato quello di fare un sacco di sperimentazione con le impostazioni che ho potuto scoprire che valorizza avrebbe 'rompere' il software.

Fare i guasti avvengono durante periodi di tempo specifici? Se sì, dove e quando? È solo alcune persone che sembrano riprodurre l'errore? Che serie di ingressi sembrano invitare il problema? Quale parte della domanda non fallire su? Ha il bug sembra più o meno intermittente in campo?

Quando ero un software tester miei principali strumenti in cui una carta e penna per registrare le note delle mie azioni precedenti - ricordo un sacco di dettagli apparentemente insignificanti è di vitale importanza. Osservando e la raccolta di piccoli pezzi di dati per tutto il tempo il bug apparirà a diventare meno intermittente.

Risposto il 09/12/2008 a 16:17
fonte dall'utente

voti
1

Alcune domande si potrebbe chiedere a te stesso:

  • Quando ha fatto questo pezzo di codice ultimo lavoro senza problemi.
  • Cosa è stato fatto da quando ha smesso di funzionare.

Se il codice non ha mai funzionato l'approccio sarebbe diverso, naturalmente.

Almeno quando molti utenti cambiano un sacco di codice per tutto il tempo questo è uno scenario molto comune.

Risposto il 09/12/2008 a 15:53
fonte dall'utente

voti
1

In questa situazione, in cui niente funziona, io presento la registrazione supplementare.

Ho anche aggiungere a notifiche e-mail che mi mostrano lo stato dell'applicazione quando si rompe.

A volte aggiungo in contatori delle prestazioni ... ho messo i dati in una tabella e guardare le tendenze.

Anche se non si presenta, si sta restringendo le cose. In un modo o nell'altro, si potranno finire con le teorie utili.

Risposto il 09/12/2008 a 15:47
fonte dall'utente

voti
1

Questi tipi di insetti sono molto frustrante. Estrapolano fuori per diverse macchine con diversi tipi di hardware personalizzato che potrebbero essere a loro (come alla mia azienda), e il ragazzo oh ragazzo non diventa un incubo. Al momento ho diversi bug come questo in questo momento al mio lavoro.

La mia regola: non risolvere il problema se non riesco a riprodurre me o mi ha presentato con un registro che mostra chiaramente qualcosa di sbagliato. In caso contrario, non posso verificare il mio cambiamento, né posso verificare che il mio cambiamento non si è rotto niente altro. Naturalmente, è solo una regola empirica - che faccio fare delle eccezioni.

Credo che tu abbia ragione di essere preoccupati con l'approccio del vostro colleuge.

Risposto il 09/12/2008 a 15:44
fonte dall'utente

voti
0

Semplicemente: chiedere all'utente che ha riportato esso.

Mi basta usare uno dei reporter come un sistema di verifica. Di solito la persona che era disposto a segnalare un bug è più che felice di aiutarvi a risolvere il suo problema [1]. Basta darle la versione con una possibile soluzione e chiedere se il problema è scomparso. Nei casi in cui l'insetto è una regressione, lo stesso metodo può essere utilizzato per bisettrice dove il problema si è verificato dando all'utente il problema più versioni da testare. In altri casi, l'utente può anche aiutare a eseguire il debug del problema dandole una versione con più funzionalità di debug.

Ciò limiterà gli effetti negativi di una possibile correzione a quella persona, invece di indovinare che qualcosa correggere il bug e poi in seguito rendersi conto che hai appena pubblicato un "bug fix" che non ha alcun effetto o nel peggiore dei casi un effetto negativo per la stabilità del sistema.

È inoltre possibile limitare i possibili effetti negativi del "bug fix", dando la nuova versione ad un numero limitato di utenti (ad esempio, a tutti quelli che ha segnalato il problema) e rilasciando la correzione solo dopo.

Anche quelli che lei può confermare che la correzione che hai fatto le opere, è facile aggiungere test che assicura che il fix rimarrà nel codice (almeno a livello di unit test, se il bug è difficile da riprodurre su più alto livello di sistema ).

Naturalmente questo richiede che tutto ciò che si sta lavorando su supporti questo tipo di approccio. Ma se non mi sarebbe davvero fare tutto il possibile per consentirgli - gli utenti finali sono più soddisfatti e molti dei problemi più difficili tecnologia solo andare via e le priorità sono chiare quando lo sviluppo può interagire direttamente con gli utenti finali del sistema.

[1] Se avete mai segnalato un bug, molto probabilmente sa che molte volte la risposta da parte del team di sviluppo / manutenzione è in qualche modo negativo dal punto di vista degli utenti finali o non ci sarà alcuna risposta a tutti - soprattutto in situazioni in cui il bug non può essere riprodotto dal team di sviluppo.

Risposto il 05/09/2014 a 11:50
fonte dall'utente

voti
0

Una volta che si comprende appieno il bug (e questo è un grande "una volta"), si dovrebbe essere in grado di riprodurre a piacimento. Quando viene scritto il codice di riproduzione (test automatizzati), a risolvere il bug.

Come arrivare al punto in cui si capisce il bug?

Strumento il codice (log come un matto). Lavora con il vostro QA - sono bravi a ricreare il problema, ed è necessario organizzare per avere piena dev kit di strumenti a vostra disposizione sulle loro macchine. Utilizzare strumenti automatizzati per memoria non inizializzata / risorse. Semplicemente guardare il codice. Nessuna soluzione facile lì.

Risposto il 09/12/2008 a 19:56
fonte dall'utente

voti
0

A meno che non ci sono grandi vincoli di tempo, non iniziare a testare le modifiche fino a quando posso riprodurre in modo affidabile il problema.

Se davvero si doveva, suppongo che si possa scrivere un banco di prova che sembra innescare a volte il problema, e aggiungerlo alla vostra suite di test automatizzati (si dispone di una suite di test automatizzato, giusto?), E quindi rendere il vostro cambiamento e di speranza che banco di prova non manca mai di nuovo, sapendo che se non hai realmente risolvere nulla, almeno ora hai più possibilità di catturare esso. Ma per il momento si può scrivere un banco di prova, si ha quasi sempre cose ridotti fino al punto in cui non si è più a che fare con un (apparentemente) situazione così non deterministica.

Risposto il 09/12/2008 a 19:06
fonte dall'utente

voti
0

Questi problemi sono sempre stati causati da:

  1. Problemi di memoria
  2. Problemi Threading

Per risolvere il problema, è necessario:

  • Strumento il codice (Aggiungere dichiarazioni di registro)
  • Code Review threading
  • allocazione di memoria Code Review / dereferenziazione

Le revisioni del codice saranno molto probabilmente avvenire solo se si tratta di una priorità, o se si dispone di un forte sospetto su quale codice è condiviso dalle molteplici segnalazioni di bug. Se si tratta di un problema di threading, quindi controllare la vostra sicurezza thread - rendere variabili sicuri accessibile da entrambi i fili sono protetti. Se si tratta di un problema di memoria, quindi controllare i vostri accantonamenti e dereferenziazioni e soprattutto diffidare di codice che alloca e restituisce la memoria, o codice che utilizza l'allocazione di memoria da qualcun altro che può essere di rilasciarlo.

Risposto il 09/12/2008 a 15:47
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more