25 Stimmen

Speicher-/Heap-Verwaltung über DLLs hinweg

Obwohl es sich offenbar um ein sehr häufiges Problem handelt, habe ich nicht viele Informationen gefunden: Wie kann ich eine sichere Schnittstelle zwischen DLL-Grenzen in Bezug auf die Speicherzuweisung schaffen?

Es ist allgemein bekannt, dass

// in DLL a
DLLEXPORT MyObject* getObject() { return new MyObject(); }
// in DLL b 
MyObject *o = getObject();
delete o;

kann durchaus zu Abstürzen führen. Da aber Interaktionen wie die oben beschriebene nicht ungewöhnlich sind, muss es eine Möglichkeit geben, eine sichere Speicherzuweisung zu gewährleisten.

Natürlich könnte man eine

// in DLL a
DLLEXPORT void deleteObject(MyObject* o) { delete o; }

aber vielleicht gibt es bessere Möglichkeiten (z.B. smart_ptr?). Ich las über die Verwendung von benutzerdefinierten Allokatoren beim Umgang mit STL-Containern als gut.

Meine Anfrage bezieht sich also eher auf allgemeine Hinweise auf Artikel und/oder Literatur, die sich mit diesem Thema befassen . Gibt es spezielle Fehler, auf die man achten muss (Ausnahmebehandlung?), und ist dieses Problem nur auf DLLs beschränkt oder sind auch gemeinsam genutzte UNIX-Objekte "betroffen"?

2voto

the_mandrill Punkte 28354

Eine andere Möglichkeit, die unter bestimmten Umständen anwendbar sein kann, besteht darin, alle Zuweisungen und Freigaben innerhalb der DLL zu halten und zu verhindern, dass das Objekt diese Grenze überschreitet. Sie können dies tun, indem Sie ein Handle bereitstellen, so dass das Erstellen eines MyObject erstellt es innerhalb des DLL-Codes und gibt ein einfaches Handle zurück (z.B. ein unsigned int ), über die alle Operationen des Kunden abgewickelt werden:

// Client code
ObjHandle h=dllPtr->CreateObject();
dllPtr->DoOperation(h);
dllPtr->DestroyObject(h);

Da alle die Zuordnung geschieht innerhalb der DLL können Sie sicherstellen, dass es aufgeräumt wird, indem in einem shared_ptr. Dies ist ziemlich genau die Methode, die John Lakos in Large Scale C++ vorschlägt.

1voto

In einer "mehrschichtigen" Architektur (sehr häufiges Szenario) ist die am tiefsten liegende Komponente dafür verantwortlich, eine Richtlinie für die Frage zu erstellen (könnte sein shared_ptr<> wie oben vorgeschlagen oder "der Anrufer ist für das Löschen verantwortlich" oder "niemals löschen, sondern anrufen releaseFooObject() wenn er fertig ist und danach nicht mehr darauf zugreift" oder ...), und die Komponente, die dem Benutzer näher ist, ist für die Einhaltung dieser Richtlinie verantwortlich.

Durch den bidirektionalen Informationsfluss sind die Zuständigkeiten schwieriger zu charakterisieren.


Ist dieses Problem nur auf DLLs beschränkt oder sind auch UNIX Shared Objects betroffen?

Eigentlich ist es noch schlimmer: Sie können dieses Problem genauso gut mit statisch gelinkten Bibliotheken haben. Es ist das Vorhandensein von Code-Grenzen innerhalb eines einzigen Ausführungskontextes, der die Möglichkeit bietet, eine Einrichtung zu missbrauchen oder falsch zu kommunizieren.

1voto

Ich habe geschrieben ein Artikel über die Verwendung der benutzerdefinierten Deleter-Funktionen von unique_ptr in C++11, um Objekte über DLL-Grenzen (oder gemeinsam genutzte Objektbibliotheken in Linux) zu übergeben. Die in diesem Artikel beschriebene Methode "verschmutzt" die unique_ptr-Signatur nicht mit dem Deleter.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X