Results 1 to 9 of 9

Thread: Memory management met dynamische dll's

  1. #1
    EPandaException
    Join Date
    Nov 2005
    Location
    Den Haag
    Posts
    107

    Memory management met dynamische dll's

    Hallo allemaal!

    Momenteel loop ik tegen iets aan waar ik even geen eenvoudige oplossing voor kan vinden.
    Ik heb een modulair opgebouwde applicatie waarbij een lichtgewicht executable functies opstart vanuit dll's, waarbij strings, dynamische array's en collections worden uitgewisseld.
    Zodra alle functies vanuit een dll niet meer in gebruik zijn wordt deze afgesloten. Op zich weinig spannends, totdat de dll een string vult die vanuit de executable is gedefinieerd.
    Dit levert mij een fijne uitdaging op in de vorm van reference counters die ik tot nu toe vrij aardig wist op te lossen middels kopieren naar TBytes arrays voordat ik de dll afsluit.
    Ik heb het al geprobeerd middels SimpleShareMem, maar dit lijkt vrij weinig uit te maken. Waarschijnlijk denk ik gewoon te moeilijk, maar ik zie het even niet meer.
    Mijn vraag is eigenlijk, hoe dit probleem zo zuiver en eenvoudig mogelijk opgelost kan worden?

    Als voorbeeld het volgende scenario.

    De applicatie wordt opgestart, en deze vraagt de gebruiker een bedrijf te selecteren en in te loggen. Hiervoor wordt een dll geladen voor de bedrijfskeuze, en een andere voor het inlogscherm.
    Zodra een van de keuzes is gemaakt, wordt de respectievelijke dll afgesloten en komt de volgende vraag.
    De bedrijfskeuze bepaalt welke database er gekozen wordt, en de gegevens hiervan moeten door alle connection objecten worden overgenomen. De keuze in gebruiker bepaalt rechten en welke vensters wel of niet gebruikt mogen worden.
    In beide gevallen moet er string data onthouden worden die gevuld wordt vanuit een dll, waarbij ik nog steeds moet kunnen lezen en schrijven.

    Ik ben al geholpen met een idee voor hoe dit te doen, dan kom ik er vast wel uit! Code snippet er bij is uiteraard mooi meegenomen indien beschikbaar.

    Alvast bedankt!

    Mvgr,
    Panda
    "Promoting back-end server connectivity since before 2000"

  2. #2
    Marius
    Join Date
    Jul 2013
    Location
    Groningen
    Posts
    176
    Ik heb altijd geleerd (met vallen en opstaan denk ik) dat je voor dll's ShareMM moet gebruiken (die zowel in de hoofd applicatie als in de DLL aanwezig moet zijn) zodat er maar 1 memory manager aanwezig is met als neveneffect dat strings 'intact' blijven. Misschien dat delphi 2010 en hoger er een betere oplossing voor heeft? (ik beken, zolang is het geleden dat ik dll's heb gebruikt, is SimpleShareMem de oplossing voor de nieuwe delphi's?).

    Is dit een oplossing? https://groups.google.com/forum/#!to...sm/i3CjbzMfE34

  3. #3
    Senior Member
    Join Date
    Dec 2003
    Location
    Den Haag
    Posts
    199
    Is het echt nodig om met dll's te werken? Het voordeel van packages is dat zelfde memory manager wordt gebruikt. Althans, het moet mogelijk zijn om zo op te zetten dat de applicatie en de packages dezelfde memory manager gebruiken. Als je vraagt naar zo zuiver en eenvoudige oplossing van probleem, is dit de richting denk ik.

    Vanuit mijn geheugen, het is ook al weer tijdje geleden, memory manager huist in rtl.dcp package, en als je bij de project options van de applicatie 'use run-time packages' aanvinkt, en voor zorgt dat zowel de applicatie als de package de rtl package gebruikt, dan wordt de memory manager gedeeld als ik het goed heb.

    Maar jij gebruikt waarschijnlijk dynamische run-time packages, en dan wordt het iets complexer. Eerst een common package definieren met daarin het rtl package, en zowel applicatie als package deze common package laten gebruiken. Op deze manier gebruiken ze dezelfde memory manager. Al weer tijdje geleden voor mij dat ik zo iets nodig had, maar volgens mij zat zo ongeveer in elkaar.

  4. #4
    I7 7700K 32Gb Win10 Pro Wok's Avatar
    Join Date
    Dec 2002
    Location
    Alkmaar
    Posts
    1,986
    Kan je voor het afsluiten niet een functie of procedure aanroepen, met als parameter de gegevens die je wilt bewaren.
    Daarbij denk ik dan in de richting van een Thread, daar worden ook gegevens gesynchroniseerd.
    Ik heb geen ervaringen hiermee, maar Threads zijn hier meerder malen te sprake geweest.
    Bijvoorbeeld deze : Object-properties-lezen-uit-draaiende-TThread

    Peter
    10.3.3, Delphi2010, of Lazarus 2.0.8

  5. #5
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,195
    Denk eraan dat naast memory management, IS en AS over EXE<->DLL grenzen heen is ook niet helemaal lekker is.

    En alle oplossingen blijven vereisen dat alles (EXE en DLL) met dezelfde Delphi gemaakt worden. De interne structuren van de managed types moeten blijven matchen.
    (dus geen main programma dat dlls gemaakt in oudere versies gemaakt gebruikt)

  6. #6
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,195
    Quote Originally Posted by Erwin View Post
    Is het echt nodig om met dll's te werken? Het voordeel van packages is dat zelfde memory manager wordt gebruikt.
    Nee dat is sharemem. Packages zorgen ervoor dat _alle_ state maar een keer in het systeem voor komt. VMTs, memorymanager, maar ook dingen als (default)formatsettings etc.

    Een programma met packages is grotendeels vergelijkbaar met een programma verdeeld over EXE en DLLs. Een geheel zeg maar. Gewoon dlls (met of zonder sharemem) blijven individuele programma's die met elkaar communiceren.

  7. #7
    EPandaException
    Join Date
    Nov 2005
    Location
    Den Haag
    Posts
    107
    Thanks iedereen tot dusver, even mijn repliek hier onder.

    @Marius2: Ik werk met Delphi XE6. SimpleShareMem zou iets vergelijkbaars moeten doen als ShareMem, maar dan zonder een borlandmm.dl te hoeven meegeven. In theorie moet dat het probleem oplossen, maar dat doet het dus niet.

    @Erwin: Ik heb een keer gestoeid met bpl's maken ipv dll's, maar die kreeg ik niet gecompileerd omdat een aantal units die ik nodig had niet in een package mochten zitten. De exacte foutmelding ben ik even kwijt, maar het was wel de reden waarom ik er niet mee verder kan.

    @Wok:
    Ik doe al eigenlijk zo iets, middels een localize procedure. Zie code hier onder.

    @marcov: Gelukkig zit bij mij alles wel in dezelfde Delphi. Ik heb een general unit met een blok globale vars die ik steeds aan de dll's meegeef. Bij types anders als dynamische arrays en dus ook strings gaat het prima, anderzijds gaat het mis.

    Onderstaand wat ik er momenteel in heb zitten, wellicht dat jullie nog iets zien wat ik beter anders kan doen? Alvast bedankt!

    Declaratie:
    Code:
    type
    
      TStrObj = record
         private
           FString : string;
           PString : ^string;
           FCopyString : string;
           PCopyString : ^string;
           function FGetString() : string;
           procedure FSetString(AString : string);
         public
           property Val : string read FGetString write FSetString;
           procedure Localize();
         end;
    Implentatie:

    Code:
    { TStrObj }
    
    function TStrObj.FGetString: string;
    begin
      // Eerst zeker weten dat deze bestaan
      if PString = nil then
      begin
        FString := '';
        PString := @FString;
        FCopyString := '';
        PCopyString := @FCopyString;
      end;
    
      // Dereferenced value teruggeven.
      Result := PString^;
    end;
    
    procedure TStrObj.FSetString(AString: string);
    var i : Integer;
    begin
      // Eerst zeker weten dat deze bestaan
      if PString = nil then
      begin
        FString := '';
        PString := @FString;
        FCopyString := '';
        PCopyString := @FCopyString;
      end;
    
      PString^ := ''; // Inhoud eerst clearen
    
      // Hier niet rechtstreeks, char is als het goed is niet reference counted.
      for i := 1 to Length(AString) do
        PString^ := PString^ + AString[i];
    
    end;
    
    procedure TStrObj.Localize;
    var i : Integer;
    begin
      // Deze procedure wordt alleen in de main exe aangeroepen zodat
      // alle pointers lokaal zijn.
    
    
      // Eerst zeker weten dat deze bestaan
      if PString = nil then
      begin
        FString := '';
        PString := @FString;
        FCopyString := '';
        PCopyString := @FCopyString;
      end;
    
    
      PCopyString^ := PString^; // Geen var string voor de scope van deze procedure, geeft AV's.
      PString^ := ''; // Inhoud eerst clearen.
    
      // Hier niet rechtstreeks, char is als het goed is niet reference counted.
      for i := 1 to Length(PCopyString^) do
        PString^ := PString^ + PCopyString^[i];
      // Tot aan dit punt geen probleem.
    
      PCopyString^ := ''; // AV hier
    end;
    Het probleem zal vast al eerder ergens gebeuren, maar het gaat pas echt bij het einde van Localize mis.

    Volgorde is:
    Localize
    Roep DLL aan.
    DLL past Val aan.
    Localize opnieuw. <- En hier dus de AV
    Sluit DLL
    "Promoting back-end server connectivity since before 2000"

  8. #8
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,195
    Pstring is denk ik niet veiliger dan gewoon string. Iedere assignment via depstring^ rommelt toch weer met de refcount.

    Je zal echt naar pchar niveau moeten, en als je een pchar mee krijgt van een ander programma deel, de inhoud altijd kopieren.

  9. #9
    EPandaException
    Join Date
    Nov 2005
    Location
    Den Haag
    Posts
    107
    Quote Originally Posted by marcov View Post
    Pstring is denk ik niet veiliger dan gewoon string. Iedere assignment via depstring^ rommelt toch weer met de refcount.

    Je zal echt naar pchar niveau moeten, en als je een pchar mee krijgt van een ander programma deel, de inhoud altijd kopieren.
    Hi Marcov, (en de rest!)

    Meeste keren heb ik voldoende aan 255 karakters genoeg, dus pak ik ShortString. In de uitzonderlijke gevallen dat ik meer nodig heb (lijsten doorsturen) pak ik een event die de string afhandeld.
    Dat gaat zo te zien altijd goed. Probleem is dus aan mijn kant opgelost.

    Bedankt iedereen!

    Mvgr,
    Panda
    "Promoting back-end server connectivity since before 2000"

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •