Visual Leak Detector ohne Callstack

Und alle paar Monate das gleiche Problem:

Verdammt, den Fehler kenne ich … das hatte ich schon mal … Wie war noch gleich die Lösung?

Unsere heutige Episode aus der Serie Was ich mir merken sollte heißt: “Visual Leak Detector ohne Callstack”


Die erste Lektion heißt:

Voraussetzung: Immer die neueste Version installieren

Wenn man auf vielen Maschinen arbeitet, kommt es schon mal vor, dass man z.B. für Windows 7 eine Version herunterlädt (oder geladen und abgelegt hat), die super funktioniert.
Doch die gleiche Version produziert unter Windows 10 Crashes beim Start eines Programms.

Die Lösung: Neueste Version installieren

Denn mit jeder neuen Version von Visual Studio, der C Runtime oder dem Betriebssystemkern sind Anpassungen am Leak-Detector erforderlich. Das Teil “hackt” sich schließlich zwischen die APIs um Fehler zu finden, wenn da was nicht passt, wird das Tool ungewollt zur Malware, die jede Menge undefiniertes Verhalten und seltsame Crashes produzieren kann.

Problem: Keine Debug Infos beim Callstack vorhanden

Das “geilste” Feature des Leak Detectors ist, dass er am Ende des Programms den Allokierungs-Callstack des Leaks anzeigt (weil er den immer brav mitloggt).

Und eben diese Aufrufliste wird mit Quellcode-Datei und Zeilennummer schön ordentlich ausgegeben, damit Visual Studio per Doppelklick sofort zur Leak-Zeile springen kann.

Das funktionierte von Studio 2005 bis 2012 “out-of-the-box”. Doch seit Studio 2015 werden zwar Code-Adressen angezeigt, der Verweis zur Quelldatei fehlt aber … folglich hilft einem die Info recht wenig.

Es sieht dann so aus:

 1WARNING: Visual Leak Detector detected memory leaks!
 2---------- Block 290 at 0x000000003222D1C0: 100 bytes ----------
 3  Leak Hash: 0x47A1C106, Count: 1, Total 100 bytes
 4  Call Stack (TID 11700):
 5    ntdll.dll!RtlAllocateHeap()
 6    vbincopy.exe!0x00007FF68312B5AA()
 7    vbincopy.exe!0x00007FF68312B32D()
 8    vbincopy.exe!0x00007FF68312EF9F()
 9    vbincopy.exe!0x00007FF6830E0F3E()

Lösung: Debug Info VOLLSTÄNDIG generieren

Kurz gesagt:

Man muss die Option
Generate Debug Information optimized for sharing and publishing
unter Linker - Debugging - Generate Debug Info aktivieren oder den Switch /DEBUG:FULL anfügen.

In den neueren Studio-Versionen wurde ein neues verkleinertes Format für die guten alten PDB Dateien als Standard eingeführt.

Damit kann der Detector nicht mehr Datei und Zeilennummer auflösen. Mit der genannten Einstellung funktioniert aber wieder alles wie gewohnt.

… und es sieht dann so aus:

 1WARNING: Visual Leak Detector detected memory leaks!
 2---------- Block 290 at 0x00000000736EE2D0: 100 bytes ----------
 3  Leak Hash: 0x36F1F623, Count: 1, Total 100 bytes
 4  Call Stack (TID 16100):
 5    ntdll.dll!RtlAllocateHeap()
 6    d:\...\new_array.cpp (29): vbincopy.exe!operator new[]()
 7    d:\...\vbincopy.cpp (141): vbincopy.exe!gate::VBinCopy::Form_Closed() + 0xA bytes
 8    d:\...\delegates.hpp (278): vbincopy.exe!gate::Delegate2<gate::ui::Form *,gate::ui::EventArg *>::method_dispatcher_impl<gate::VBinCopy>()
 9    d:\...\delegates.c (37): vbincopy.exe!gate_delegate_invoke() + 0x14 bytes

Ah, eine Allokation in Form_Closed()? Wozu denn das?

Fazit

Bin gespannt, wie lange es jetzt dauert, bis ich wieder vor einem “nicht funktionierenden” Leak Detector stehe und mich wieder frage: “Warum?”

Es wäre eine Überlegung wert die Option /DEBUG:FULL durch CMake hinzuzufügen. Aber letztendlich nutze ich für die aktive Entwicklung im GATE Projekt ohnehin meine selbst erstellten Projektdateien, weil ich nicht immer CMake bemühen möchte, wenn ich 2 neue Dateien hinzufüge.

Und damit bleibt die Frage weiter aktiv:

Wie lange wird es wohl dauern, bis ich diese Einstellung wieder vergesse.


Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!