Speicher über Shared Objekt Grenzen hinweg reservieren und freigeben



  • Hallo Leute,

    ich würde gerne mal folgendes klären. Ich habe ein Programm, das sich Module aus shared objects (also .so) nachläd. Nun habe ich das Problem, dass es passieren kann, das ein Modul Speicher allociert, dieser Speicher aber in einem anderen Modul wieder freigegeben wird (ist das unter Linux überhaupt ein Problem?). Irgendwo meine ich mal gelesen zu haben, dass die boost::shared_ptr die ich benutze den richtigen Deallocator rumschleppen, so das der Speicher doch richtig freigegeben wird.

    Sollte das stimmen, was ist dann aber, wenn das Modul, das den Speicher allociert hat, entladen wird (bzw von mir das handle auf die .so freigegeben wird), bevor alle smart pointer auf diesen Speicher zerstört sind? Führt dann der nächste zerstörte smart pointer zu undefiniertem Verhalten? Falls es noch eine Rolle spielt, es geht um c++ code, also new und delete.



  • jeder prozess befindet sich inklusive seiner module in seinem eigenen adresseraum. verwendet ein module malloc/free oder new/delete, so sind das (im allgemeinen) die gleiche funktionen wie die, die die ausführbare datei verwendet. im speziellen wissen diese funktionen gar nicht, ob sie von einem modul aus aufgerufen wurden oder nicht.

    das bedeutet, dass der speicher grundsätzlich auch nach entladen noch allokiert bleibt, sofern er im modul dynamisch allokiert wurde. statische variablen werden beim entladen des moduls ebenso beseitigt wie der code des moduls.

    wird ein modul entladen, kann es sein, dass noch verschiedene funktionen vorher aufgerufen werden. hat man z.b. eine statische instanz einer klasse, die einen destruktur hat, im modul erstellt, wird der destruktor dieser klasse für diese instanz aufgerufen. sollte der den speicher freigeben, der im konstruktor der klasse allokiert wurde, ist er natürlich auch für den rest des prozesses freigegeben.



  • Ja, das ist mir soweit auch eigentlich klar. Mir ging es eher drum, ob ich in einer dynamisch geladenen .so new aufrufen kann um Speicher zu reservieren und diesen dann per delete im Hauptprogramm wieder freigeben kann (auch wenn die .so schon längst wieder entladen wurde).

    Grade bei c++ wird ja nun aber eine runtime gelinkt, die vermutlich dann new und delete realisiert. Wenn dem so ist wäre obiges unproblematisch solange beide die gleiche runtime linken. Unter Windows ist es sehr gut möglich, dass das nicht der Fall ist. Bei Linux bin ich nicht ganz sicher, aber dort gibts doch auch unterschiedliche Versionen oder?



  • Unter Linux sollte das kein Problem sein. Es gibt einen fixen ABI-Standard und wenn die Library und dein Hauptprogramm inkompatible ABI-Versionen benutzen, dann solltest du sie noch nicht mal zusammen gelinkt bekommen. Daher solltest du dir darum keine Sorgen machen, dass ist unter Linux viel viel komfortabler und besser geregelt, als unter Windos.



  • du musst nur folgendes beachten: durch delete könnte ein destruktur aufgerufen werden. sollte der code dieses destruktors im modul enthalten sein, wirst du das modul beim aufruf von delete natürlich noch brauchen.

    in manchen fällen ist das aber kein problem. wenn der code des destruktors nicht im modul sondern in einer (noch geladenen) anderen bibliothek steht, ist das kein problem.
    pass dir hier aber mit vererbung auf. erbt eine klasse des moduls von einer klasse außerhalb des moduls, ist mit großer wahrscheinlichkeit ein destruktor auch im modul vorhanden.

    solltest du im modul nur speicher für die in c++ eingebauten datentypen (int, float, char, ...) allokieren, kannst du das modul vor dem freigeben entladen.



  • Wenn du den Destruktor von einem Objekt aufrufen willst, dann wäre es keine gute Idee, genau diesen Code, den du ausführen willst, aus dem Speicher zu entfernen, oder?



  • Jup, ich seh das Problem. Das macht das Modul entladen natürlich etwas komplizierter.



  • HyperSonic schrieb:

    Jup, ich seh das Problem. Das macht das Modul entladen natürlich etwas komplizierter.

    Ja. Aber wenn das so ist, wie hier schon erwähnt, dass der Destruktor keinen Code enthält, deine Klasse nur Daten enthält (keine Objekte) und keinen Destruktor, also eine POD (Plain old Data) Struktur ist. Dann müsste das gehen...


Anmelden zum Antworten