… oder auch: Es gibt Tage, da könnte man sich in der Tischplatte verbeißen…
Wir haben vor ein paar Wochen einen sehr mystischen Fehler in unserer Software gefunden.
Das Problem war eine Funktion, die einen (const) Zeiger auf einen Datenblock bekam.
Die Funktion hat aber unter Umständen eine UI-Interaktion (Dialog) ausgelöst und die entsprechende offene Nachrichtenschleife hat es wiederum einen Hintergrundthread erlaubt (unter bestimmten Umständen) Nachrichten an den Mainthread zu senden, der wiederum die Anzeige aktualisierte und auch den Datenblock, der eben noch als Zeiger übergeben wurde, ungültig machte.
Die Funktion sah in etwa so aus:
bool CSomeClass::SomeAction(const S_FOO *pData)
{
...
pData war nun ungültig und wurde verändert, war aber immer noch gültiger Speicher in dem ein paar Ids aus einer Datenbank standen. Das Programm stürzte nicht ab. Tat aber aufgrund der falschen Ids auch nicht das, was es eigentlich sollte.
Der Code wurde dann wie folgt geändert und ein entsprechender Kommentar geschrieben:
bool CSomeClass::SomeAction(const S_FOO &data)
{
// We use a copy of the result object. There is a chance that the
// global result gets replaced while we are inside this routine and
// the storage where our pointer points gets deleted and replaced
// by a new result object.
...
Oha. Aber was passierte hier. Anstatt wirklich eine Kopie zu verwenden, wurde wieder nur ein Zeiger verwendet. Nur diesmal in Form einer Referenz.
Es wird nun niemanden wundern., dass mir die selbe Fehlebeschreibung wieder auf den Tisch flatterte. Im Debugger wurden die selben Probleme festgestellt und ich musste dreimal auf die Code-Zeile schauen und den Kommentar dreimal lesen, bevor ich verstand was hier geändert wurde.
- Fehler erkannt.
- Fehler dokumentiert.
- Fehler aber nicht gefixed.
So hätte es aussehen müssen:
bool CSomeClass::SomeAction(const S_FOO data)
{
...
PS: Ich oute mich mal. Der Trottel war ich…