Prima di tutto, rassegnati al fatto che questo richiederà probabilmente un lungo tempo per risolverlo. Ho avuto un bug qualche anno fa che ci è voluto quasi un anno per sistemarlo, perché era così dispendioso in termini di tempo da riprodurre.
Un consiglio è assicurarsi che il codice venga compilato senza avvisi e passi l'analisi statica. Ottieni una recensione tra pari. Potresti avere qualcosa come una condizione di gara con una probabilità dello 0,001% di verificarsi. Gli strumenti di analisi statica possono aiutarti a trovare questi tipi di bug.
Assicurati che il tuo codice sia super pulito. Elimina tutti la ripetizione e riduci le tue funzioni. Elimina tutte le ottimizzazioni che potresti aver fatto e sostituiscile con un codice che è così semplice da leggere, eventuali errori si diffonderanno come un pugno. Solo dopo che il tuo codice funziona dovresti reinserire le ottimizzazioni, una per una con un test tra una e l'altra. Il codice che è più difficile da leggere è il codice che con ogni probabilità contiene un bug.
Scrivi un ton di test unitari, che coprono tutti i casi limite del tuo errore contabilizzato. Lo scenario più probabile è che tu abbia fatto un errore accidentalmente con uno di loro.
La prossima cosa che puoi fare è scrivere del codice extra per aiutarti a individuare e restringere il bug. Caricalo con asserzioni e voci di registro. Automatizza il rilevamento del bug nei tuoi risultati intermedi, magari confrontandolo con un algoritmo più lento ma più affidabile. Scrivi il codice per verificare le condizioni che dovrebbero essere impossibili da colpire, quindi imposta un punto di interruzione se lo fa. Rendi possibile salvare e riavviare il tuo algoritmo da uno stato intermedio.
Un'altra tecnica interessante che ho visto di recente ha dimostrato di avere un grande effetto in questo eccellente TED talk è quello di creare una visualizzazione. Il cervello umano può trovare schemi e anomalie molto, molto più facilmente in forma visiva.
Sottolineerò nuovamente la necessità di essere paziente. Se provi a correre e cerchi di prendere scorciatoie, probabilmente ti ci vorrà più tempo. Non aver paura di apportare grandi cambiamenti al solo scopo di eseguire il debug. Non sprecerai il tuo sforzo precedente, questo è il motivo del controllo del codice sorgente.