Speicherverwaltungs Dll & Bedingungen



  • //---------------------------------------------------------------------------
    // Wichtiger Hinweis über die DLL-Speicherverwaltung, falls die DLL die statische
    // Version der Laufzeitbibliothek (RTL) verwendet:
    //
    // Wenn die DLL Funktionen exportiert, die String-Objekte (oder Strukturen/
    // Klassen, die verschachtelte Strings enthalten) als Parameter oder Funktionsergebnisse übergibt,
    // muß die Bibliothek MEMMGR.LIB im DLL-Projekt und anderen Projekten,
    // die die DLL verwenden, vorhanden sein. Sie benötigen MEMMGR.LIB auch dann,
    // wenn andere Projekte, die die DLL verwenden, new- oder delete-Operationen
    // auf Klassen anwenden, die nicht von TObject abgeleitet sind und die aus der DLL exportiert
    // werden. Durch das Hinzufügen von MEMMGR.LIB wird die DLL und deren aufrufende EXEs
    // angewiesen, BORLNDMM.DLL als Speicherverwaltung zu benutzen. In diesem Fall
    // sollte die Datei BORLNDMM.DLL zusammen mit der DLL weitergegeben werden.
    //
    // Um die Verwendung von BORLNDMM.DLL, zu vermeiden, solten String-Informationen als "char *" oder
    // ShortString-Parameter weitergegeben werden.
    //
    // Falls die DLL die dynamische Version der RTL verwendet, müssen Sie
    // MEMMGR.LIB nicht explizit angeben.
    //---------------------------------------------------------------------------

    Das Stück Text kennt ja sicher jeder von euch, der schonmal was mit Dlls gemacht hat. Eigentlich sieht das ganz leicht verständlich aus und ist es wahrscheinlich auch für die meisten aber ich habe trotzdem so meine Problemchen damit und brauche Hilfe.

    1. Warum sollte man überhaupt die Verwendung der borlndmm.ll vermeiden?

    2. Wenn ich String-Informationen weitergebe soll ich möglichst char* benutzen und kein AnsiString, so ist das doch gemeint, oder? Ich nehme mal an, das ich dann TStringList z. Bsp. auch nicht verwenden dürfte, oder? Und wie sieht es aus mit der Benutzung von "string"?

    3. Sobald ich irgendeine Klasse in meiner dll benutze die nicht von Tobject abgeleitet ist brauch ich die dll auch?! Umgekehrt wärs für mich logischer. Ist TObject nicht etwas das aus der vcl (also von Borland) kommt, wieso muss ich das dann benutzen um auf die Speicherverwaltungsdll verzichten zu können?
    Oder habe ich das falsch verstanden?

    4. Alles was euch zu dem Thema wichtig erscheint und ich wahrscheinlich vergessen habe zu Fragen, bitte gleich mit beantworten. 🙂



  • hallo,

    1. zum einen mußt du die dll immer mitgeben.

    2. du kannst problemlos tstringlis und ansistring verwenden, aber sobald du nach außen (z. b. übergabeparameter einer funktion oder rückgabe einer funktion) hin arbeitest solltest du char* bzw. PChar verwenden, da dies c-konform ist und somit wird der memorymanager von borland nicht benötigt.

    mfg

    murph



  • Danke für die Info. Kann jetzt eventl. noch einer was zu den Klassen sagen.



  • Guten Tag!

    Ich muß diesen bei der Suche im Forum gefunden Thread "wieder zum Leben erwecken", weil ich die Sache mit "DLL & AnsiString & Speicherverwaltung" ein Problem habe.
    Folgendes:

    - Ich habe folgende Funktion in einer DLL

    extern "C" AnsiString __declspec(dllexport) TestAnsiString();
    AnsiString TestAnsiString()
    {
      AnsiString sTest = "Dies ist ein Test!";
      return sTest;
    }
    

    - Diese DLL wird dann in einem anderen Programm statisch gebunden und die Funktion aufgerufen:

    extern "C" AnsiString __declspec(dllimport) TestAnsiString();
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      ShowMessage(TestAnsiString());
    }
    

    - Sowohl die DLL als auch die aufrufende Anwendung werden ohne dynamische RTL und ohne Laufzeit-Packages erstellt, und so muß MEMMGR.LIB nicht eingebunden werden.

    // Falls die DLL die dynamische Version der RTL verwendet, müssen Sie
    // MEMMGR.LIB nicht explizit angeben.

    - Nun bekomme ich zwar den Text mit ShowMessage angezeigt, danach aber eine Fehlermeldung:

    Ungültige Zeigeroperation.

    - Danach hatte ich memmgr.lib und borlndmm.lib (einzeln und auch zusammen) in den beiden Anwendungen (DLL und DLL aufrufende) eingebunden, jedoch ohne Erfolg. Ich bekomme jedes Mal die oben genannte Fehlermeldung.

    - Folgendes funktioniert logischerweise wunderbar:

    char* TestChar()
    {
      AnsiString sTest = "Dies ist ein Test!";
      char *cTest = "";
      strcpy(cTest, sTest.c_str());
      return cTest;
    }
    

    Meine Frage:
    Wie kann ich sonst noch die obige DLL-Funktion von einem anderen Programm aufrufen? Ich möchte es gerne verstehen.

    Vielen Dank für jeden Tipp
    xy



  • *schieb*



  • Mal grundsätzlich: Dein obiger Code mit dem strcpy ist haarsträubend falsch. Wo reservierst du bitte Speicher für deinen String?
    Und wo hält schlussendlich der Debugger an?

    -^junix



  • junix schrieb:

    Mal grundsätzlich: Dein obiger Code mit dem strcpy ist haarsträubend falsch. Wo reservierst du bitte Speicher für deinen String?

    Danke für den Hinweis!

    junix schrieb:

    Und wo hält schlussendlich der Debugger an?

    Wenn ich debugge, dann geht es bis zur ShowMessage ohne Fehler. Dann erscheint die Message und direkt nach dem Klicken auf OK-Button kommt dann die Fehlermeldung.

    MfG
    xy



  • kennt keiner das Problem?
    Anders gefragt:
    Wie kann ich am besten eine DLL-Funktion programmieren, die AnsiString zurückliefert? Es muß doch irgendwie möglich sein, oder?

    Ich wäre für Hilfe sehr dankbar, denn ohne die komme ich nicht weiter. Ich habe gegoogelt und das Problem auch dort gefunden jedoch keine Lösung (außer daß die DLL "mit dynamischen RTL" und "mit Laufzeit Packages" zu erstellen, was mir aber nicht hilft, denn die EXE wird weitergegeben)

    MfG
    xy



  • Warum willst du unbedingt einen AnsiString zurückgeben. 😕 Du könntest doch genauso über AnsiString::c_str() ein *char ** zurückgeben und es am anderen Ende wieder an einen AnsiString übergeben.
    Vielleicht lässt sich so das Problem umgehen. 😃



  • Ich hab gerade oben gesehen, dass du sowas ähnliches versucht hast. Wenn du die ganze Geschichte ein bisschen umschreibst, dann müsste es eigentlich funktionieren.



  • Maffe001 schrieb:

    Warum willst du unbedingt einen AnsiString zurückgeben. 😕 Du könntest doch genauso über AnsiString::c_str() ein *char ** zurückgeben und es am anderen Ende wieder an einen AnsiString übergeben.
    Vielleicht lässt sich so das Problem umgehen. 😃

    Hallo Maffe001,

    das Problem mit AnsiString::c_str() ist hier beschrieben:
    http://www.c-plusplus.net/forum/viewtopic.php?t=39296

    Andere Idee?
    Danke
    xy



  • Hmm, schon klar. Aber wenn du die ganze Sache direkt an einen AnsiString übergibst, dann sollte doch eigentlich alles glatt gehen.

    //DLL.h
    #define DLLEXPORT extern "C" __declspec(dllexport) //der Übersichtlichkeit 
                                                       //halber
    
    DLLEXPORT char *Return_String ();
    //-------------------------------------------------------------
    
    //DLL.cpp
    char *Return_String()
    {
      AnsiString Test = "Dies ist ein Test.";
    
      return Test.c_str();
    }
    //-------------------------------------------------------------
    
    //App.h
    
    #define DLLIMPORT extern "C" __decspec(dllimport) //die Übersicht wieder
    
    DLLIMPORT char *Return_String();
    //-------------------------------------------------------------
    
    //App.cpp
    
    int Get_String ()
    {
      AnsiString TestString = "";
    
      TestString = AnsiString(Return_String());
      return ...;
    }
    //-------------------------------------------------------------
    

    So hab ich mir jetzt das Ganze gedacht. Da die Übergabe passiert ist, sollte es doch keine Probleme mehr geben.
    Ich muss dazu sagen, dass ich das selber noch nicht gemacht habe. Ist nur so ne Idee, wie ich da ran gehen würde. 😃



  • Am Anfang hatte ich es auch so versucht, und ich kann mich erinnern, daß ich dann ein "Access Violation" bekommen habe. Dann habe ich bei der Suche den oben genannten Beitrag gefunden.
    Ich versuche es trotzdem nochmal.

    Danke
    xy



  • Sag mal Bescheid, wenn's klappt. Muss doch wissen, ob meine geistigen Ergüsse auch was taugen. 😃



  • Maffe001 schrieb:

    Du könntest doch genauso über AnsiString::c_str() ein *char ** zurückgeben und es am anderen Ende wieder an einen AnsiString übergeben.

    Wenn ich das nur schon lese wird mir schlecht.... Mal wieder ein typisches Beispiel für das Sprichwort "Der schlimmste Schlag ist der Ratschlag"...

    Vielleicht solltest du mal in der FAQ hier nachschauen was über die Verwendung von c_str() so an bemerkenswertem steht...

    -junix



  • Wenn mein "Ratschlag" so schlimm ist. Dann klär mich auf. Ich bin ja gern bereit zu lernen.
    Ich dachte halt, dass es vielleicht gar nicht so schlecht ist, wenn er ein *char ** zurückgibt. So kann er vielleicht seine DLL auch bei anderen Compilern mit einbauen. So weit ich weiss, ist doch AnsiString borlandspezifisch, oder nicht? 😕



  • junix schrieb:

    Vielleicht solltest du mal in der FAQ hier nachschauen was über die Verwendung von c_str() so an bemerkenswertem steht...

    Hallo junix,

    ich hatte ihm schon darauf aufmerksam gemacht.

    xy schrieb:

    Hallo Maffe001,

    das Problem mit AnsiString::c_str() ist hier beschrieben:
    http://www.c-plusplus.net/forum/viewtopic.php?t=39296

    MfG
    xy



  • Ich zitier mich zwar nicht gerne selber aber...

    junix schrieb:

    [...]Vielleicht solltest du mal in der FAQ hier nachschauen was über die Verwendung von c_str() so an bemerkenswertem steht...

    Euch sollte man allen mal eine Implementation von delete bzw. delete [] aufs Auge drücken, welche die Daten vom freigegebenen Speicherbereich zurücksetzt. Auf das ihr begreift, was da genau im Hintergrund abläuft.

    Die von dir vorgeschlagene Version ist besonders gefährlich, da das AnsiString Objekt welches den Zeiger zurückliefert nach dem Return gar nicht mehr existiert.

    -junix



  • Das mit c_str() ist mir schon bewusst. Ich bin ja nu nicht ganz verblödet. Nur über die Geschichte, was mit dem String nach dem return passiert, habe ich nicht nachgedacht. 😞

    Aber gut man lernt ja nie aus. Dann ist mein Vorschlag jetzt, den String in eine Datei zu schreiben, ein Event zu setzen, ihn auslesen und die Datei löschen. Das mit dem Event ist vielleicht sogar noch nicht einmal nötig, da man ja über eine Funktion das regeln könnte, wann er schreibt. Allerdings sollte man die Datei vielleicht von einem Mutex schützen lassen, da auch erst gelesen werden soll, wenn fertig geschrieben ist.
    Klingt ganz schön umständlich, was? Meinungen dazu?



  • @junix,
    Könntest Du bitte folgendes genauer erklären?

    junix schrieb:

    Euch sollte man allen mal eine Implementation von delete bzw. delete [] aufs Auge drücken, welche die Daten vom freigegebenen Speicherbereich zurücksetzt. Auf das ihr begreift, was da genau im Hintergrund abläuft.

    @Maffe001,
    wenn es nicht anders geht, dann würde ich (ganz am Ende) Deinen Vorschlag mit der Datei versuchen.

    Danke
    xy


Log in to reply