heap allozierung vs. boost::shared_ptr im kontext von dll verwendung



  • ahoi,
    ich habe folgende problematik und hoffe jemand kann das richtungsweisend kommentieren:

    1. Eine C++ Anwendung lädt eine DLL
    2. Es wiederrum in der Anwendung eine Funktion der DLL aus 1. aufgerufen, die über einen Call-By-Reference Parameter einen Pointer auf einen auf dem Heap alloziertes Objekt vom Typ A zurückgibt.
    3. Die Anwendung hat eine Klasse B, welche eine Member vom Typ boost::shared_ptr<A> hat die mit dem Pointer aus 2. initialisiert wird.
    4. Am Ende der Anwendung beim Destruktor von B crasht die Anwendung (Aufrufstack sieht nach Freigebeversuch der in 3. angesprochenen Member aus)

    Frage: kann / darf ich Heap Speicher so freigeben ? Falls nein, wie macht man sowas generell (in DLL angelegten Heap) auf Anwendungsebene freigeben) ??

    Vielen Dank.



  • Generell sollte Speicher, der von der DLL reserviert wird, auch von der DLL wieder freigegeben werden.



  • Ok, aber ist denn obiges wirklich ein "no-go"?? Letztlich passiert doch obiges in einem adressraum (heap des prozesses) wieso kann/darf ich diesen so nicht freigeben?



  • ok, fuer alle, die es interessiert:

    das obig von mir geschilderte vorgehen ist "bad-practise" und tatsaechlich ein no-go:
    der heap gehoert nicht dem prozess sondern der CRT (c-runtime). Wenn exe und DLL ggf. verschieden gebaut wurden, benutzen sie unter Umstaenden verschiedene CRT, was bei obigem Szenario zwangslaeufig zu Problemen fuehrt.

    Besser ist es in der DLL statt eines raw-pointers einen smart-pointer (z.B. boost::shared_ptr) mit entsprechend konfigurierter Deleter-Funktion
    zurückzugeben.

    zum weiterlesen fuer interessierte:
    http://stackoverflow.com/questions/13625388/is-it-bad-practice-to-allocate-memory-in-a-dll-and-give-a-pointer-to-it-to-a-cli



  • pepe75 schrieb:

    Besser ist es in der DLL statt eines raw-pointers einen smart-pointer (z.B. boost::shared_ptr) mit entsprechend konfigurierter Deleter-Funktion
    zurückzugeben.

    Damit verschiebst du das Problem bloss, denn dann müssen DLL und EXE die selbe shared_ptr Implementierung benutzen.
    Bzw. je nachdem wie diese shared_ptr Implementierung aussieht bist du das Problem mit dem CRT Heap nichtmal los (Stichwort "control block" bzw. "shared count object").

    Ich kenne folgende "korrekte" Lösungswege:

    1. Du schreibst eine ganz besimmte Build-Umbegung vor (Compiler, Compiler-Settings etc.). Diese muss dann die DLL Runtime verwenden. Dann löst sich das Problem in Luft auf und du kannst es so machen wie du es machen wolltest.

    2. Du exportierst aus der DLL eine "DeleteA" Funktion, und erstellst dann erst in der EXE einen Smart-Pointer mit einem Deleter der die "DeleteA" Funktion der DLL aufruft.

    3. Du verwendest intrusive Reference-Counting. D.h. dein A Objekt hat eine "AddRef" und eine "Release" Funktion, und als Smart-Pointer verwendest du z.B. boost::intrusive_ptr. Übergeben tust du dabei immer rohe Zeiger, und jeder der Shared-Ownership mit übernehmen will erzeugt sich seinen eigenen Smart-Pointer. (Bei intrusive Reference-Counting geht das im Gegensatz zu shared_ptr & Co. ja problemlos.)

    Jede dieser drei Möglichkeiten hat ihre Berechtigung. Welche für dich passt, musst du selbst entscheiden.
    (1) ist z.B. gut, wenn die Vorgabe der exakten Build-Umbegung nicht stört und man viele verschiedene Klassen/Factory-Funktionen hat.
    (2) ist z.B. gut wenn man ein C-kompatibles Interface bauen muss bzw. ohne Umstände damit auskommt.
    (3) ist gut wenn man ein C++ Interface verwenden will. Setzt allerdings voraus dass man gewisse Dinge hat die alle beteiligten Compiler gleich machen. z.B. die Calling-Convention für Memberfunktionen, das VTable-Layout und wenn man dynamic_cast verwenden will auch die RTTI Informationen.



  • Vielen dank für die ausführliche empfehlung. Ich habe letztlich weg 2 gewählt allerdings auch nach näherem betrachten meines codes gemerkt, dass es nocht nicht mal unbedingt shared ptr sein müssen. Den 3ten fall werde ich mir vielleicht auch nochmal anschauen rein aus interesse.


Anmelden zum Antworten