Ich habe eine Funktion mit einem Prototyp wie folgt:
%Vor%Diese Funktion wird in meiner Hauptfunktion in einem anderen Programm aufgerufen, das diese DLL lädt und benutzt.
%Vor%Wenn ich von dieser Funktion zurückkomme, erhalte ich einen Heap-Fehler:
Windows hat in Programm.exe einen Haltepunkt ausgelöst.
Dies kann auf eine Beschädigung des Heaps zurückzuführen sein, die auf einen Fehler in programm.exe oder eine der DLLs, die es geladen hat.
Dies kann auch daran liegen, dass der Benutzer F12 gedrückt hat Programm.exe hat den Fokus.
Das Ausgabefenster enthält möglicherweise mehr Diagnoseinformationen.
Als ich mit meinem Code herumspielte, bemerkte ich ein paar seltsame Beobachtungen:
1. Wenn die Länge des übergebenen Strings weniger als 11 Zeichen beträgt, erhalte ich keine Fehler, sobald ich weitere Zeichen hinzufüge, erscheint der Fehler.
2. Wenn der Typ des Parameters von std::string
in std::string&
geändert wird, verschwindet der Fehler. Die Idee, die Referenz zu übergeben, kam von hier .
3. Ich habe den Hauptteil der Funktion auskommentiert. Die Operationen dort haben nichts mit der erzeugten Ausnahme zu tun.
4. Das Ändern des Parametertyps von std::string
nach char*
löst auch das Problem.
Was könnte diesen Fehler verursachen? Wie löse ich es?
Am wahrscheinlichsten sind Abstürze aufgrund der Tatsache, dass DLLs in Windows ihren eigenen privaten Heapspeicher haben.
Beim Kompilieren Ihrer Funktion hat der Compiler Code für den Destruktor std::string
generiert, um seine Argumente zu bereinigen. Dieser Code gibt den reservierten Speicher auf dem DLL-Heap frei. Die Anwendungs-EXE generiert jedoch auch eigenen Code für den Konstruktor std::string
, der den Code im Programmheap zuweist. Wenn Sie auf dem einen Heap und auf dem anderen Heap reservieren, tritt ein undefiniertes Verhalten auf, und Sie stürzen ab.
Warum kleine Zeichenketten den Fehler nicht auslösen - viele std::string
Implementierungen inline kleine Zeichenketten in die Struktur selbst, um Heap Overhead zu vermeiden. Wenn Ihre Zeichenfolge klein genug ist, um zu passen, muss keine Speicherzuordnung stattfinden und daher scheint es zu funktionieren ... solange Sie dieselbe STL-Version für EXE und DLL verwenden und der Schwellenwert für Inlining niemals geändert wird.
Um dieses Problem zu vermeiden, übergeben Sie keine Objekte per Wert an DLLs (außer sie sind POD-Objekte ), und geben Sie ein Objekt in einer anderen DLL oder EXE nicht frei, als es erstellt wurde. Vermeiden Sie auch die Weitergabe von STL- oder C ++ - Bibliotheksobjekten, da sich ihre Implementierung in verschiedenen Versionen von C ++ unterscheiden kann Compiler. Übergeben Sie stattdessen POD-Objekte oder C-Grundtypen wie const char *
.
Beim Exportieren von DLL-Funktionen ist es am besten, wenn sie nur ganzzahlige Datentypen akzeptieren, d. h. int oder pointer (nicht sicher über float und double).
Wenn Sie eine Zeichenfolge übergeben müssen, übergeben Sie sie als const char *
. Wenn Sie die DLL-Funktion zum Zurückgeben einer Zeichenfolge benötigen, übergeben Sie einen char *
-Zeiger an die DLL, wo die DLL dies tun würde schreibe die Zeichenfolge.
Verwenden Sie niemals Speicher, der von der DLL außerhalb der eigenen Funktionen der DLL zugewiesen wird, und übergeben Sie nie Wertstrukturen, die ihren eigenen Konstruktor / Destruktor haben.
Wahrscheinlich haben Sie eine Verbindung mit der statischen Version von C Runtime hergestellt. Es ist daher keine gute Idee, eine DLL zu erstellen, die mit der statischen Version von C runtime verknüpft ist. Dies kann viele Probleme verursachen, zum Beispiel in Ihrem Programm Ihre EXE Speicher von privaten Haufen von statischen C-Laufzeit zuweisen, dass es mit ihr verknüpft ist, dann in Ihrer DLL möchten Sie diesen Heap löschen und einen neuen Heap erstellen (da Sie hinzufügen möchten einige Daten in die Eingabe-Zeichenfolge und es muss seinen Puffer vergrößern), so wird es zu einem Fehler führen. Der einfachste Ansatz besteht darin, alle Teile Ihres Programms (EXE und DLL) mit der DLL-Version von C Runtime zu verknüpfen, sodass alle denselben Heap von MSVCRTXX.dll
verwendenTags und Links c++ dll exception-handling heap-corruption