Ich habe ein Programm, in dem ich, zum Teil für die informative Protokollierung, die Namen einiger verwendeter Klassen ausspreche (insbesondere füge ich einen Eintrag zu einem Protokoll hinzu, der in den Zeilen von Messages::CSomeClass transmitted to 127.0.0.1
steht). Ich mache das mit einem Code ähnlich dem folgenden:
Und bevor jemand darauf hinweist, stelle ich fest, dass die Ausgabe von typeinfo::name
implementierungsspezifisch ist.
Laut MSDN
Die% member-Funktion% co_de gibt eine
type_info::name
an eine nullterminierte Zeichenfolge zurück, die den lesbaren Namen des Typs darstellt. Der Speicher, auf den verwiesen wird, wird zwischengespeichert und sollte nie direkt freigegeben werden.
Wenn ich jedoch mein Programm im Debugger verlasse, wird jede "neue" Verwendung von const char*
als Speicherleck angezeigt. Wenn ich die Informationen für 2 Klassen ausspreche, erhalte ich 2 Speicherlecks und so weiter. Dies deutet darauf hin, dass die zwischengespeicherten Daten niemals freigegeben werden.
Obwohl dies kein großes Problem ist, sieht es chaotisch aus, und nach einer langen Debugsitzung könnte es leicht echte Speicherlecks verbergen.
Ich habe mich umgeschaut und einige nützliche Informationen gefunden (eine SO-Antwort gibt einige interessante Informationen über wie typefinfo implementiert werden kann ) ), aber ich frage mich, ob dieser Speicher normalerweise durch das System freigegeben werden sollte, oder ob ich etwas tun kann, um die Lecks beim Debuggen nicht zu bemerken.
Ich habe einen Back-up-Plan, der die typeinfo::name()
-Methode selbst programmieren soll und nicht auf getMessageName
angewiesen ist, aber ich würde trotzdem gerne wissen, ob ich etwas verpasst habe.
Eine andere Lösung besteht darin, das zugrunde liegende Problem zu korrigieren. Dies ist nicht wirklich ein Speicherleck, nur ein falscher Bericht. Die Speicherblöcke, die der Zeichenfolge "typepinfo ()" und "name ()" zugewiesen sind, erhalten den falschen Blocktyp. Es ist wahrscheinlich keine gute Idee, diese Erinnerung zu "befreien", da die CRT versuchen wird, sie wieder freizugeben. Die gute Nachricht ist, dass dies in VS2012 (_MSC_VER 1700 +) endgültig behoben wurde.
Da dies nur für _DEBUG-Builds gilt, kann das Folgende eine sicherere Lösung sein. Die Funktion _FixTypeInfoBlockUse () sollte wie oben erwähnt aufgerufen werden, kurz bevor der Moduleintrittspunkt (main, WinMain, etc.) Verlassen wird.
%Vor%Ich bin gerade auf dieses Problem gestoßen, als ich versucht habe, das Protokoll von VLD zu säubern. Ja, das ist ein bekannter Fehler , die nur in VC11 festgelegt ist. Es existiert in früheren Versionen von MSVC, einschließlich 2010. Dieser Fehler wird nur angezeigt, wenn Sie MFC verwenden. Wenn Sie MFC als DLL anstelle von statischer Bibliothek verwenden, wird der Speicherverlust weiterhin vorhanden aber nicht erkannt werden.
Es gibt einen globalen Cache von type_info
Namen und er ist nicht gelöscht (der Auszug von <typeinfo>
):
Die Idee ist, diesen Cache zu löschen. Diese Funktion funktioniert für mich:
%Vor% Rufen Sie clear_type_info_cache()
vor dem Beenden auf. Sie können es mit atexit
oder rufen Sie es sofort auf, bevor Sie WinMain verlassen
%Vor%Wie Chris Parton in den Kommentaren darauf hingewiesen hat, scheint dies ein bekannter Fehler , zumindest mit der Version des Compilers, den ich verwende - ein Upgrade auf VC11 würde das Problem beheben, wenn ich ein Upgrade durchführen könnte.
Der Versuch, die Ausgabe von typeinfo::name()
zu löschen, funktioniert teilweise:
Allerdings gibt es immer noch einige Speicherlecks - ich habe gerade bemerkt, dass ich früher zwei Lecks pro Aufruf bekommen habe (vielleicht weil die Klassen in einem Namensraum liegen?). Bei Verwendung der obigen Codeversion ging dies pro Aufruf auf ein Leck zurück.
Eine andere Lösung, die scheinbar funktioniert, ist die Verknüpfung in der dynamischen Version der MFC-Bibliotheken (ja, ich benutze MFC, verurteile mich nicht), anstatt die statische Version.
VS speichert Typinformationen in einer einfach verknüpften Liste. Auf den Header dieser Liste kann über eine undurchsichtige Struktur zugegriffen werden, auf die über den Namen __ type_info_root_node zugegriffen werden kann. Eigentlich ist es eine SLIST_HEADER Struktur.
Win32-API verfügt über eine Reihe von Nebenläufigkeitsfunktion, um mit solchen Strukturen zu arbeiten. In diesem Fall müssen Sie alle Knoten dieser Liste löschen.
%Vor%Aktualisiert: VLD 2.5.1 meldet Speicherverluste bei type_info :: name () in VS2015 Update 3 nicht.
Tags und Links memory-leaks c++ visual-c++ typeid typeinfo