DLL- Heap aufräumen oder nicht?



  • berniebutt schrieb:

    theta schrieb:

    ... ich finds ziemlich simpel: Alles was ich anfordere an Resourcen (Speicher, File Handles, etc.) gebe ich dann zurück wenn ich es nicht mehr benötige.

    Das ist und bleibt guter Programmierstil, selbst wenn das System mit einigem alleine aufräumt! 😋

    100% Ack.



  • berniebutt schrieb:

    theta schrieb:

    ... ich finds ziemlich simpel: Alles was ich anfordere an Resourcen (Speicher, File Handles, etc.) gebe ich dann zurück wenn ich es nicht mehr benötige.

    Das ist und bleibt guter Programmierstil, selbst wenn das System mit einigem alleine aufräumt! 😋

    Naja, ich hab' ja geschrieben, wo das Zeug herkommt, nämlich vom Controller und da störts nicht, wenns aufm Heap liegenbleibt, im Gegenteil, zwei der Tables werden noch benötigt.

    Im Allgemeinen ist es ja keine Frage des guten Stils, ob ich mir die Schläfe desinfiziere, bevor ich mir eine Kugel durch die Birne jage - das ist eher bizarr.

    Ein Teil der Funktionalität soll jedoch unter Win laufen und weil ich nicht gleich die Source hergeben mag, packe ich's in eine DLL und muß halt die Spielregeln von Win beachten.

    Also, da ich die Codebasis behalten möchte und mit HeapCreate dann auch alles auf HeapAlloc usw. umbiegen müßte, würde das zu einem heftigen #ifdef- Dschungel führen, dafür wäre nach HeapDestroy() die Landschaft wieder sauber.
    Wenn ich bei malloc/free bleibe, sollte ich hingegen selbst aufräumen - hab' ich das richtig verstanden? 😕

    Hab' mich mal wegen Tippfaulheit für zweiteres entschieden und jetzt drei Funktionen, die die DLL exportiert, ein Initialisierungsaufruf, der das Teil parametriert (und auch die Tabellen aufbaut), einen Aufruf zur Konvertierung und einen, der die Tabellen wieder abreißt.
    Ist damit den Win- Konventionen genüge getan? 😕



  • Ich bin so, ich würde auch auf dem kleinsten Micro Dingsbums das zeugs wieder freigeben, wenn ichs angefordert habe...



  • theta schrieb:

    Ich bin so, ich würde auch auf dem kleinsten Micro Dingsbums das zeugs wieder freigeben, wenn ichs angefordert habe...

    Es gibt Fälle, in denen es nicht nur grund- und sinnlos ist, sondern kontraproduktiv.

    Du rückst das in die Nähe einer Zwangshandlung, aber ich versichere Dir, man darf darüber wirklich nachdenken, deswegen frage ich ja hier nach.

    Aber was soll's, Monk ist ja auch ganz lustig ... 😉



  • pointercrash() schrieb:

    Es gibt Fälle, in denen es nicht nur grund- und sinnlos ist, sondern kontraproduktiv.
    ... Zwangshandlung, aber ich versichere Dir, man darf darüber wirklich nachdenken, deswegen frage ich ja hier nach.

    Wann und wo?
    Willst Du beim Programmieren selbst die Kontrolle behalten oder willst Du auf ein Dir unbekanntes Systemverhalten vertrauen?
    Stellst Du Dein Auto mit laufendem Motor in die Garage in der Erwartung, wenn man das Garagentor zumacht geht der Motor schon aus?
    Die Kugel kannst Du Dir auch so in die Birne jagen...
    Dann brauchen wir hier nicht weiter über Dein Anliegen nachzudenken...



  • berniebutt schrieb:

    pointercrash() schrieb:

    Es gibt Fälle, in denen es nicht nur grund- und sinnlos ist, sondern kontraproduktiv.
    ... Zwangshandlung, aber ich versichere Dir, man darf darüber wirklich nachdenken, deswegen frage ich ja hier nach.

    Wann und wo?
    Willst Du beim Programmieren selbst die Kontrolle behalten oder willst Du auf ein Dir unbekanntes Systemverhalten vertrauen?
    Stellst Du Dein Auto mit laufendem Motor in die Garage in der Erwartung, wenn man das Garagentor zumacht geht der Motor schon aus?

    Wenn ich fertig mit Fahren bin, halte ich vermittels der Bremse einfach an, und der Motor geht ganz von alleine aus. Aber es gibt Leute, die mir vorschreiben wollen, daß ich zuerst bei laufendem Motor ausgekuppelt anhalten soll, dann die Zündung unterbrechen soll und dann wieder einkuppeln. Wozu?



  • Wenn garantiert ist, daß

    (1) die DLL nur einmal geladen wird und
    (2) die DLL frühestens bei Prozessende "entladen" wird,

    dann ist das ständige Auf- und wieder Abbauen der (wiederverwendbaren) Tabellen in der Tat eine chronische Zwangshandlung.



  • Wenn der Inhalt der Tabellen sowieso immer der Selbe ist und bleibt, stehen doch bereits zum Zeitpunkt des Compilierens alle Informationen fest. Wozu muss dann überhaupt noch der Umweg über alloc gegangen werden?



  • berniebutt schrieb:

    Willst Du beim Programmieren selbst die Kontrolle behalten oder willst Du auf ein Dir unbekanntes Systemverhalten vertrauen?

    das ist kein unbekanntes verhalten. windoof macht alle handles eines prozesses zu, wenn er beendet wird (wie auch immer das geschieht, normal oder durch absturz). dazu gehört z.b. dass files geschlossen, speicher freigegeben und sogar TCP-verbindungen gekillt werden (es wird ein RST an die gegenstelle geschickt).

    berniebutt schrieb:

    Stellst Du Dein Auto mit laufendem Motor in die Garage in der Erwartung, wenn man das Garagentor zumacht geht der Motor schon aus?

    naja, prinzipientreue ist aber kein für deine grauen zellen, auch wenn manche das glauben.
    🙂



  • edit:

    ;fricky schrieb:

    naja, prinzipientreue ist aber kein <ersatz> für deine grauen zellen, auch wenn manche das glauben.
    🙂



  • pointercrash() schrieb:

    +gjm+ schrieb:

    Ich persönlich fände es eher erschreckend wenn ein OS auf das Byte genau weiß, wieviel Speicher eine DLL/EXE benötigen wird. Und zwar vor dem laden schon.

    Mich persönlich schockiert eher, daß Win nicht weiß, was es mit dem Entladen einer DLL alles aus dem Speicher kippen kann.
    Mich verunsichert volkards Eintrag zusätzlich, nachdem ich gar nix machen müßte - aber was soll's?

    Windows kann das nicht für dich besorgen, da Windows nicht wissen kann, welcher Speicher denn nun freigegeben werden kann.
    Kann ja genausogut sein, dass deine DLL Speicher anfordert, einen Zeiger an das Programm übergibt, und das Programm diesen Speicher auch nach Entladen der DLL weiterverwendet.

    Wenn über DLL und EXE über eine gemeinsame Schnittstelle Speicher anfordern und freigeben (HeapAlloc mit dem Process-Heap oder so), geht das wunderbar. Und ist von Windows aus gesehen vollkommen OK.
    Vermutlich wird sowas selten gemacht, aber woher soll Windows wissen, dass nicht gerade deine DLL es macht.

    Aber sich auf OS rauszureden ist oft die einfachste Möglichkeit 😉



  • pointercrash() schrieb:

    ... aber "resources allocated on behalf of the current process" versteh' ich jetzt einfach nicht. Dann wär' das ja jenseits jeden Witzes, wenn es keinen lokalen Heap gäbe, der nur im Kontext der DLL existieren würde.

    Also bliebe der Speicher im Heap auch nach unload der DLL reserviert - wofür?

    Diese Formulierung kommt noch aus der Win16 Zeit. Lass dich davon nicht verunsichern. Wenn der Prozess sterben geht, ist er weg. Aus, Ende. Mitsamt allem Speicher den irgendwelche DLLs irgendwann angefordert haben.

    Ist allerdings egal, wenn du FreeLibrary unterstützen willst, da du dann trotzdem selbst saubermachen solltest.



  • hustbaer schrieb:

    pointercrash() schrieb:

    +gjm+ schrieb:

    Ich persönlich fände es eher erschreckend wenn ein OS auf das Byte genau weiß, wieviel Speicher eine DLL/EXE benötigen wird. Und zwar vor dem laden schon.

    Mich persönlich schockiert eher, daß Win nicht weiß, was es mit dem Entladen einer DLL alles aus dem Speicher kippen kann.
    Mich verunsichert volkards Eintrag zusätzlich, nachdem ich gar nix machen müßte - aber was soll's?

    Windows kann das nicht für dich besorgen, da Windows nicht wissen kann, welcher Speicher denn nun freigegeben werden kann.
    Kann ja genausogut sein, dass deine DLL Speicher anfordert, einen Zeiger an das Programm übergibt, und das Programm diesen Speicher auch nach Entladen der DLL weiterverwendet.

    naja, eine dll besteht nur aus code und daten. sie kann selber keinen speicher anfordern, dass macht der prozess, der die dll geladen hat, z.b. indem er eine funktion in der dll aufruft (wenn mich nicht alles täuscht, wird sogar die DLLMain im kontext des jeweiligen prozesses aufgerufen und nicht von csrss.exe oder so). jedenfalls, wenn eine dll entladen wird, werden nur der code und die daten der dll freigegeben, nicht aber dynamischer speicher, den ein prozess (z.b. über die dll) geholt hat. der verschwindet erst, wenn der prozess selber beendet wird.
    🙂



  • fricky.
    du seppl.
    das ist jetzt, etwas komplizierter formuliert, und vielleicht um 0,1% "korrekter", dasselbe was ich geschrieben habe.



  • hustbaer schrieb:

    du seppl.

    Ebenfalls. Es steht bereits auf Seite 2, dass das eine Sache des Prozesses ist. Euch beide Dödels hätte es nicht mehr gebraucht.



  • berniebutt schrieb:

    Wann und wo?
    Willst Du beim Programmieren selbst die Kontrolle behalten oder willst Du auf ein Dir unbekanntes Systemverhalten vertrauen?

    Bei mir ist ein Controllerprogramm meist auf Listen basierend aufgebaut, die werden beim Start erzeugt und verbleiben, bis der Strom abgedreht wird. Wozu soll ich die wieder abbauen, beim Systemneustart wird ja auch der Heap neu erzeugt?
    Hinderlich wird das sogar beim Brown- oder Blackout, wenn Du den Systemzustand in nichtflüchtigen Speicher retten mußt, weil Dir nur ein paar Millisekunden dafür bleiben. Jetzt an alle Module Signal zu geben, den Heap zu räumen, ist Stuß, da geht die Sicherung vor. Selbst danach läßt man besser die Finger davon und fährt den Prozessor in einen elektrisch sicheren Zustand, weil die Dinger v.a. beim Brownout durch Querströme manchmal totalen Vollquatsch anrichten können.

    +gjm+ schrieb:

    Wenn garantiert ist, daß

    (1) die DLL nur einmal geladen wird und
    (2) die DLL frühestens bei Prozessende "entladen" wird,

    dann ist das ständige Auf- und wieder Abbauen der (wiederverwendbaren) Tabellen in der Tat eine chronische Zwangshandlung.

    So ist es eigentlich gedacht - kann ich verhindern, daß die DLL mehrfach geladen wird?

    Mox schrieb:

    Wenn der Inhalt der Tabellen sowieso immer der Selbe ist und bleibt, stehen doch bereits zum Zeitpunkt des Compilierens alle Informationen fest. Wozu muss dann überhaupt noch der Umweg über alloc gegangen werden?

    Eben nicht. Die DLL holt sich einen Sack Parameter aus einem ini- File und baut daraus die Tabellen auf. Die bleiben solange gültig, bis man der DLL sagt: Guck nochmal nach, da hat sich was geändert. Während einer Anlagenparametrierung, die so ein, zwei Tage dauern kann, passiert das bis zu ein paar hundert mal. Danach zwar meist nie wieder aber nach einer Reparatur z.B. kommt der Zirkus zurück.

    hustbaer schrieb:

    Ist allerdings egal, wenn du FreeLibrary unterstützen willst, da du dann trotzdem selbst saubermachen solltest.

    OK, ist das korrekt, wenn ich in DllMain unter reason DLL_PROCESS_DETACH meine Putzfrauenfunktion unterbringe? Sieht irgendwie nach der richtigen Stelle aus ...



  • Eine DLL legt für jeden neuen anfordernden Prozess eine neue Instanz für die Daten an. Die einzelnen Daten der DLL-Instanzen sind also strikt unabhängig voneinander und werden in der Reihenfolge der sich verabschiedenden Prozesse auch vollständg wieder freigegeben. Dennoch sollte man in DllMain selbst alles aufräumen, was man angefordert hat.
    Nur eine DLL-Instanz zulassen? Geht auch mit einem Mutex-Objekt im Zweig DLL_PROCESS_ATTACH.
    Willst Du mehr über das Leben von Prozessen hinaus, bieten sich Files auf der Festplatte an. Was da reingeschrieben wird bleibt egal und löschen kannst Du nach freiem Belieben.
    Ich weiss nicht, ob Dir diese Hinweise weiterhelfen. Mehr vermag ich aber nicht beizutragen!



  • pointercrash() schrieb:

    So ist es eigentlich gedacht - kann ich verhindern, daß die DLL mehrfach geladen wird?

    Verhindern lässt sich das nur indem garantiert wird, daß LoadLibrary auch nur einmal aufgerufen wird. Sollte das (egal warum) nicht garantiert sein, dann leistet ein eigener Zähler in der DLL_PROCESS_ATTACH resp. DLL_PROCESS_DETACH gute (und unbestechliche) Dienste.



  • Mox schrieb:

    hustbaer schrieb:

    du seppl.

    Ebenfalls. Es steht bereits auf Seite 2, dass das eine Sache des Prozesses ist. Euch beide Dödels hätte es nicht mehr gebraucht.

    is ja gut, ich hab nicht alles gelesen, was hier steht.

    pointercrash() schrieb:

    ...kann ich verhindern, daß die DLL mehrfach geladen wird?

    das geht (siehe vorposter), aber eigentlich ist sowas doof. stell dir nur mal vor, der eine prozess hängt sich weg, aber so, dass kein fenster mehr sichtbar ist. dann musste ihn mit'm taskmanager killen, ansonsten kann keine weiterer prozess die DLL laden (firefox z.b. zickt manchmal so rum). daher isses besser, wenn du deine DLL so programmierst, dass sie mit mehreren prozessen arbeiten kann.
    btw, mit #ifdef WIN32 z.b. kannste deinen code windows-kompatibel machen. etwas so:

    // wird aufgerufen durch brown-out interrupt oder DLLMain.DLL_PROCESS_DETACH
    void shutdown (void)
    {
    #ifdef WIN32
       // hier windows-code rein, free(), HeapDestroy(), usw...
    #else
       // hier MCU code, z.b. brown-out handling usw.
    #endif
    }
    

    🙂



  • pointercrash() schrieb:

    OK, ist das korrekt, wenn ich in DllMain unter reason DLL_PROCESS_DETACH meine Putzfrauenfunktion unterbringe? Sieht irgendwie nach der richtigen Stelle aus ...

    Das ist korrekt. Nur solltest Du dann HeapAlloc/HeapFree (oder einfach nur HeapDestroy) verwenden und nicht malloc/free. Falls irgendjemand irgendwann mal auf die Idee kommen sollte, die CRT nicht statisch zu linken, geht es nämlich fürchterlich in die Hose.


Anmelden zum Antworten