[Delphi] Geheugenlek na (C++) DLL aanroep

Pagina: 1
Acties:

  • Pietb
  • Registratie: Maart 2001
  • Niet online
Ik probeer via Delphi 7 een (zelfgemaakte) C++ DLL (gebouwd in MS Visual Studio 6) aan te roepen, maar nu gaat het mis qua geheugengebruik. Dit loopt bij iedere aanroep van de DLL-functie op :(

De C++ code ziet er als volgt uit en werkt (in principe) goed:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char** Zipsearch::getStreets(char* streetPart, char* cityPart, 
              char* zipcode, char* number, int& numberOfResults)
{
    PVector* pStreets = findStreets(streetPart);

    numberOfResults = pStreets->getNumberOfElements()+1;
    int* indexArray;
    indexArray = pStreets->getArray();

    char** retValue = new char*[numberOfResults+1];

    for (int i = 0; i < numberOfResults; i++)
    {
        char* streetName =
             reinterpret_cast<char*>(&streetsMem[indexArray[i]] + 4);
        
        retValue[i] = new char[strlen(streetName)+1];
        strcpy(retValue[i], streetName);
    }

    delete pStreets;
    return retValue;        
}
Probleem hierbij is natuurlijk dat de "retvalue" eigenlijk verwijderd zou moeten worden, maar dat is weer onmogelijk doordat deze in Delphi nodig is...

In Delphi definieer ik het als volgt:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[..]

TPCharArr = array[0..MaxInt div SizeOf(PChar) - 1] of PChar;
PPCharArr = ^TPCharArr;

[..]

function getStreets (street: PChar; city: PChar; zipcode: PChar; 
                 housenr: PChar; var length: integer):
                 PPCharArr; stdcall; external 'Search.dll';

[..]

procedure ...
var
  test: PPCharArr;
  len: integer;
begin
  test := getStreets('x', '', '', '', len);

  {*
      Uitlezen van resultaten en toevoegen aan een Combobox met test^[..].
      Werkt ook goed.
  *}
end;
Dit levert natuurlijk een geheugenlek op, omdat de array die vanuit de DLL geretourneerd wordt, nergens verwijderd wordt.

Mijn eerste gedachte (na _onwijs_ lang zoeken naar een oplossing in Delphi) was om "gewoon" de DLL die array weer te laten deleten, maar dat loste mijn geheugenlek nog niet op, het geheugengebruik steeg nog steeds bij iedere aanroep van de DLL-functie.

Mijn vraag is nu dus: hoe kan ik er voor zorgen dat ik wel het geheugen dat die array in gebruik heeft netjes verwijderd wordt?

  • Aetje
  • Registratie: September 2001
  • Laatst online: 18-12-2025

Aetje

Troubleshooting met HAMERRR

Free het array in Delphi na gebruik :? Ik zie het probleem daarin eigenlijk nie...

Forget your fears...
...and want to know more...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een oplossing in Delphi is er sowieso niet, omdat je dll z'n eigen heap management heeft. Maar als je een functie in je dll maakt die het geheugen weer vijgeeft, dan zou er geen probleem moeten zijn

Een andere oplossing is een buffer mee te geven waarin het resultaat moet komen te staan... dan zet je het dus op je Delphi app's heap, en kan Delphi het zelf ook weer vrijgeven

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Pietb
  • Registratie: Maart 2001
  • Niet online
Aetje schreef op 17 November 2002 @ 21:17:
Free het array in Delphi na gebruik :?
Dat probeer ik, maar ik kan geen "test.Free();" of zo doen, die methode bestaat niet voor mijn PPCharArr. Of begrijp ik je nu verkeerd?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Pietb schreef op 17 november 2002 @ 21:24:
[...]
Dat probeer ik, maar ik kan geen "test.Free();" of zo doen, die methode bestaat niet voor mijn PPCharArr. Of begrijp ik je nu verkeerd?


zoals ik al zei kan Delphi je geheugen sowieso niet vrijgeven ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Aetje
  • Registratie: September 2001
  • Laatst online: 18-12-2025

Aetje

Troubleshooting met HAMERRR

Als je die stdcall naar een ander type call verandert (ben ff kwijt welke) dan kan je WEL geheugen dealloceren. En dan moet je met een free(test); het zaakje kunnen opruimen.

Forget your fears...
...and want to know more...


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Aetje schreef op 17 November 2002 @ 21:33:
Als je die stdcall naar een ander type call verandert (ben ff kwijt welke) dan kan je WEL geheugen dealloceren. En dan moet je met een free(test); het zaakje kunnen opruimen.


dat is echt vette bullshit, het enige wat de calltype wijzigt is de manier waarop de stack wordt opgeruimd, dat heeft niets te maken met het alloceren of dealloceren van heap geheugen

ik zal het je nog leuker maken, als je een C++ app bouwt en je gebruikt daarbij een DLL gemaakt door C++ gelinkt tegen een static runtime, dan kunnen ze nog steeds niet elkaars geheugen vrijgeven

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Euh bij vrijwel iedere Win32 Api call die strings retourneerd geef je 'n buffer mee waar ie het in kan plaatsen, en het maximale aantal tekens wat er in kan.. wellicht een goed idee?

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

pcies way Yarveih zegt. Een andere manier die ook vaak gebruikt wordt is de dll een functie te laten exporteren die het geheugen weer vrijgeeft aan de DLL kant.

We adore chaos because we like to restore order - M.C. Escher


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 28-08 20:54

Tomatoman

Fulltime prutser

Verwijderd schreef op 17 November 2002 @ 21:50:
Euh bij vrijwel iedere Win32 Api call die strings retourneerd geef je 'n buffer mee waar ie het in kan plaatsen, en het maximale aantal tekens wat er in kan.. wellicht een goed idee?
En weet je van tevoren niet hoe groot de buffer moet zijn, dan kun je in veel Win32 API calls de waarde nil in de buffer geven, waardoor de functie retourneert hoe groot de buffer moet zijn. Vervolgens alloceer je genoeg geheugen voor de buffer en roep je de functie nogmaals aan om de buffer te laten vullen.

Een goede grap mag vrienden kosten.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

tomatoman schreef op 17 November 2002 @ 22:01:
[...]

En weet je van tevoren niet hoe groot de buffer moet zijn, dan kun je in veel Win32 API calls de waarde nil in de buffer geven, waardoor de functie retourneert hoe groot de buffer moet zijn. Vervolgens alloceer je genoeg geheugen voor de buffer en roep je de functie nogmaals aan om de buffer te laten vullen.


nou weet ik toevallig wat voor app het is, en dit is geen goede optie, omdat er _veel_ gezocht moet worden... 1x zoeken om te kijken hoeveel elementen er zijn en daarna nog een keer om de array te vullen lijkt mij dan ook geen goede oplossing

Wat je ook kunt doen is de DLL z'n gealloceerde resources bij te laten houden... dan kun je bij elke functieaanroep de vorige resources vrijgeven, zodat je dat niet expliciet vanuit je app hoeft te doen. Daar komt natuurlijk wel bij dat een pointer alleen geldig is tussen 2 aanroepen van de dll, en als je een langere lifetime wilt hebben zul je de array moeten kopieren (dit is overigens ook een veelgebruikte API methode)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Pietb
  • Registratie: Maart 2001
  • Niet online
Het is reeds opgelost, een functie in de C++ DLL die de array opruimt (en alle afzonderlijke items ook, daar zat het hem in), credits gaan naar .oisyn _/-\o_
Pagina: 1