L’Heisenbug perfetto
Pochi giorni fa mi sono riscontrato nel cosidetto Heisenbug perfetto. Di solito gli Heisenbug hanno a che fare con il multi-threading circostanza per cui aggiungere qualche breakpoint al codice sfasa il timing dell’applicazione e per tanto potrebbe causare la scomparsa di un baco sotto osservazione. Nel mio caso non c’era nessun multithreading, ma bastava semplicemente “osservare” il comportamento dell’oggetto misterioso per deviarne il flusso di esecuzione. Ridotto al minimo l’Heisenbug è descritto qui sotto:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Heisenbug
{
class MyClass
{
bool here;
public override string ToString()
{
string result = here.ToString();
this.here = true;
return result;
}
public MyClass()
{
this.here = false;
// put a breakpoint on the following line
// and add 'this' to the watch window and
// then execute
Console.WriteLine(this.ToString());
}
}
class Program
{
static void Main(string[] args)
{
MyClass c = new MyClass();
Console.WriteLine(c.ToString());
}
}
}
Normalmente l’applicazione scrive False-True sulla console. Se invece si aggiunge un breakpoint nella riga del costruttore indicata e si osserva appunto l’oggetto appena instanziato il risultato diventa True-True. La cosa non è stata banale da individuare perché il tutto era offuscato da qualche altro centinaio di righe di codice e parlandone con il collega pazzo con la capigliatura più caotica della mia ne è nata una questione filosofica: ma il debugger può permettersi davvero di invocare metodi mentre un oggetto è ancora in costruzione? Girerò la domanda a quelli del team di Visual Studio per sapere se il comportamento è documentato (prescritto) da qualche parte.
-quack
Update:
Dalla regia mi suggeriscono che questo comportamento può essere disabilitato ed il valore di default in effetti makes sense.
VS – Developer 1-0 e palla al centro