Speicher eines Objektes in einer DLL wieder freigeben



  • hallo

    wie kann ich den speicher eines instanziierten objektes in einer DLL wieder freigeben?

    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
    	kkey = new KKey();
    	return 1;
    }
    

    die DLL wird statisch gelinkt ich hoffe ich verwechsle das nun nicht wieder, also ohne LoadLibrary funktion und mit gelinkter *.lib. Müsste glaub statisch und nicht dynamisch sein oder?

    Gut, dann werden exportierte funktionen verwendet und wenn ich die hauptanwendung beende (C++ Builder 6 compilierte exe anwendung mit VCL unterstützung) dann wird ja die DLL wieder freigegeben aber wie gebe ich den speicher noch frei? Kann es sein das dass objekt selbstständig von der DLL zerstört wird?

    Ich benutze derzeit eine exportierte funktion die aufräumarbeiten erledigt unteranderem eben auch den speicher wieder freigeben der beim DLL entry point angefordert wurde, dies scheint mir jedoch keine gute lösung zu sein.

    :xmas1: :xmas2:



  • kokonoko schrieb:

    die DLL wird statisch gelinkt ich hoffe ich verwechsle das nun nicht wieder, also ohne LoadLibrary funktion und mit gelinkter *.lib. Müsste glaub statisch und nicht dynamisch sein oder?

    Hehe, genau 🙂

    Grundsätzlich solltest du Speicher, der in der DLL geholt wird, dort auch wieder freigeben.
    Eine exportierte Ich-gebe-Speicher-frei Funktion ist wahrlich keine optimale Lösung. Was dagegen die Speicherverwaltung sehr (sehr sehr sehr!!!!!) vereinfacht, sind Klassen, die im Destruktor den Speicher wieder freigeben oder/und die Klasse std::auto_ptr. Damit musst du den Speicher, den du mit "new" holst, nicht mehr explizit freigeben und musst dir dahingehend kaum noch Sorgen machen.



  • In die DllMain Funktion (die du "DllEntryPoint" genannt hast) sollte inetwa folgendes rein:

    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
        switch(reason)
        {
        case DLL_PROCESS_ATTACH:
            kkey = new KKey();
            break;
    
        case DLL_PROCESS_DETACH:
            delete kkey;
            kkey = 0;
            break;
    
        case DLL_THREAD_ATTACH:
            break;
    
        case DLL_THREAD_DETACH:
            break;
        }
        return 1;
    }
    

    Und lies dir bitte die Doku zu DllMain gut durch, du solltest da drinnen z.B. keine anderen DLLs verwenden (ausser KERNEL32) oder COM Aufrufe oder ähnliches machen - alles ganz pöse.
    BTW: "new" ist beim VC je nach verwendeter Runtime ein Aufruf in eine andere DLL, also darfst du "new" da drinnen eigentlich nicht verwenden.



  • hustbaer schrieb:

    BTW: "new" ist beim VC je nach verwendeter Runtime ein Aufruf in eine andere DLL, also darfst du "new" da drinnen eigentlich nicht verwenden.

    was man jedenfalls nicht machen sollte ist: new/malloc in der dll und delete/free ausserhalb der dll. dabei treffen zwei verschiedene heap-libraries aufeinander, die nix voneinander wissen 😉
    mit 'VirtualAlloc/VirtualFree' geht's aber...
    :xmas2:



  • besten dank an euch allen 🙂 :xmas1: :xmas2:



  • ten schrieb:

    hustbaer schrieb:

    BTW: "new" ist beim VC je nach verwendeter Runtime ein Aufruf in eine andere DLL, also darfst du "new" da drinnen eigentlich nicht verwenden.

    was man jedenfalls nicht machen sollte ist: new/malloc in der dll und delete/free ausserhalb der dll. dabei treffen zwei verschiedene heap-libraries aufeinander, die nix voneinander wissen 😉
    mit 'VirtualAlloc/VirtualFree' geht's aber...
    :xmas2:

    Ja, das wieder was anderes. Und das geht wohl wenn alle Beteiligten die gleich Runtime DLL verwenden 😉

    Ich meine den Punkt dass man in DllMain keine Funktionen verwenden darf die nicht entweder in KERNEL32 oder in der eigenen DLL implementiert sind. Da eben "new" in einer der MSVC DLLs implementiert ist gehört es nicht nach DllMain rein. VirtualAlloc geht aber übrigens auch dort, da es eben in der KERNEL32 implementiert ist 🙂


  • Mod

    @hustbaer:
    1. Der OP hat aber geschrieben, dass er statisch gelinkt hat.
    2. Ist auch die Verwendung von new/delete aus einer CRT-DLL "meistens" kein Problem, wenn
    a. die selbe CRT DLL von der EXE auch verwendet wird. Explizit oder Implizit geladen. (Denn dann ist diese DllMain der CRT bereits garantiert gelaufen)
    b. Diese CRT implizit geladen wird nur durch diese DLL! (Denn dann ist diese DllMain der CRT bereits garantiert gelaufen).

    Leider muss man eben an dieser Stele wissen was man macht.
    Was MS dazu schreibt sind letzten Endes nur Guidlines, verboten ist das nicht.
    Alle MFC-DLLs (sofern nicht statisch gelinkt) leben damit, dass new/delete etc in der DllMain Phase verwendet werden. Nur ist eben hier garantiert, dass die MFC Main DLL die CRT als DLL auch benutzt und entsprechend vorher initialisiert sein muss.

    Einzig und alleine die Verwendung LoadLibrary und diesem ganzen DLLMain Gesocks bringt hier sehr oft Probleme. Und ganz und gar wenn LoadLibrary in DllMain aufgerufen wird, dann geht die Hölle los...

    Just my 2 cent's



  • @Martin Richter:
    Ja, ich weiss selbst dass es geht, ich mache es aber nicht gerne. Unter Windows 95 ging es sogar noch CoInitialize() in DllMain aufzurufen -- war auch ordentlich lästig als wir draufkamen dass das unter 2000 nichtmehr geht.
    Von daher halte ich mich lieber etwas zu sehr als etwas zu wenig an die Vorschläge von MS.


Anmelden zum Antworten