Wenn ich die new
Schlüsselwort in meiner Bibliothek (die anders aufgebaut ist als meine Hauptanwendung), wenn ich es in meiner Hauptanwendung mit delete
Besteht die Möglichkeit, dass ich einen Absturz/Fehler erhalte?
Antworten
Zu viele Anzeigen?Das kommt darauf an. Wenn es sich um eine statische Bibliothek handelt, ist wahrscheinlich alles in Ordnung - der Code wird im gleichen Kontext wie das Hauptprogramm ausgeführt und verwendet die gleiche C++-Laufzeitbibliothek. Das bedeutet, dass new
y delete
verwenden denselben Heap.
Wenn es sich um eine gemeinsam genutzte Bibliothek (eine DLL) handelt, dann ist das wahrscheinlich nicht in Ordnung. Der in der DLL laufende Code könnte eine andere C++-Laufzeitbibliothek verwenden, was bedeutet, dass das Layout des Heaps anders ist. Möglicherweise verwendet die DLL einen ganz anderen Heap.
Aufruf von delete
(im Hauptprogramm) auf einen von der DLL zugewiesenen Zeiger (oder umgekehrt) führt (im besten Fall) zu einem sofortigen Absturz oder (im schlimmsten Fall) zu einer Speicherbeschädigung, deren Aufspüren eine Weile dauern wird.
Sie haben mehrere Möglichkeiten. Die erste ist die Verwendung des Musters "Fabrikmethode" zum Erstellen und Löschen dieser Objekte:
Foo *CreateFoo();
void DeleteFoo(Foo *p);
Diese sollten no in der Header-Datei implementiert werden.
Alternativ können Sie auch eine Destroy
Methode auf das Objekt:
class Foo
{
~Foo();
public:
virtual void Destroy();
};
...wieder, implementieren Sie dies nicht in der Header-Datei. Sie würden es so implementieren:
void Foo::Destroy()
{
delete this;
// don't do anything that accesses this object past this point.
}
Beachten Sie, dass der Destruktor für Foo privat ist, so dass Sie den Foo::Destroy
.
Microsoft COM macht etwas Ähnliches, indem es eine Release
Methode, die das Objekt löscht, wenn seine Referenzanzahl auf Null sinkt.
Ja, das werden Sie. Eine einfache Lösung besteht darin, in Ihrer Bibliothek Funktionen zum Erstellen und Löschen bereitzustellen, die von der Hauptanwendung aus aufgerufen werden können. Die Create-Funktion führt die Neuanlage durch und gibt einen Zeiger zurück, der später zum Löschen an die Delete-Funktion übergeben wird.
Dieses Problem habe ich bisher nur unter Windows gesehen.
In Unix-Systemen ist es nicht üblich, gemeinsam genutzte Bibliotheken zu zwingen, sich innerhalb eines Programms mit verschiedenen Versionen derselben Bibliothek zu verbinden, und alle geladenen Symbole sind global sichtbar. Das bedeutet, dass, wenn ein Objekt in einem Teil des Codes zugewiesen und in einem anderen gelöscht wird, beide dieselbe Systembibliothek dafür verwenden.
Ich muss sagen, dass dieses Problem, das Windows mit seinen verschiedenen C-Laufzeit-DLLs verursacht, wirklich ärgerlich und unnatürlich für einen C-Programmierer ist. Schauen Sie sich die C-Bibliothek an; sie hat Funktionen wie strdup, die die Zeichenkette malloc und erwarten, dass der Programmierer free() dafür aufruft. Aber machen Sie das Gleiche in Ihrer eigenen Bibliothek unter Windows und warten Sie einfach auf die Explosion. Sie werden auch warten müssen, denn es wird nicht während der Entwicklung passieren, sondern erst, nachdem Sie die kompilierte DLL an einen anderen armen Trottel weitergegeben haben.
Alte neue Sache hat bereits darüber berichtet. Er gibt auch eine Liste der wichtigsten Lösungen von Microsoft.
- See previous answers
- Weitere Antworten anzeigen