Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Memory Leak bei rekursiven Aufruf... (https://www.delphipraxis.net/102621-memory-leak-bei-rekursiven-aufruf.html)

Niels14 1. Nov 2007 01:54


Memory Leak bei rekursiven Aufruf...
 
Hallo, ich fuehre in unserer ISAPI eine rekursive Suche in der Datenbank nach den Vorfahren von eines mir angegebenen Tiers durch.
Bei dem rekursiven Procedur Aufruf gebe ich ein TStrings Object mit, was meines Wissens nach ja nur eine Referenz auf das TString Object ist. Das TString Objekt wird nur einmal am Anfang erstellt und dann in der Funktion mitgegeben. Er erkennt den Anfang dadurch dass ich einen leeres (NIL) TString Object mitliefere. Die Web Application laeuft einwandfrei unter IIS 6.0. Aber nach der mehrmaligen Suche ist mir aufgefallen dass der Server unmengen an Speicher alloziert hat und nach dem Programm Lauf nicht mehr freigibt. Erst wenn ich den IIS resette habe ich wieder 800 MB mehr speicher! Beim Programmlauf selber wird der Speicher auch verbraucht.
Wo habe ich hier den Denkfehler?

Delphi-Quellcode:
procedure XXX.InbreedCheck(CheckAnimalsKey: String; PedigreeList: TStrings);
var
    StartNode: Boolean;
    AnimalList: TStrings;
    SireKey, DamKey, s, TempStr: String;
begin
    If PedigreeList = nil then
    begin
        StartNode := True;
        AnimalList := TStringlist.create;
        ...
    end
    else
    begin
        StartNode := False;
        ... Hole Daten fuer SireKey und DamKey
    end;

    TempStr := CheckAnimalsKey + '|';

    If SireKey <> '' then
    begin
        TempStr := TempStr + SireKey + '|';
        If pos(SireKey, AnimalList.GetText) > 0 then
            SireKey := '';
    end
    else
        TempStr := TempStr + '|';

    If DamKey <> '' then
    begin
        TempStr := TempStr + DamKey + '|';
        If pos(DamKey, AnimalList.GetText) > 0 then
            DamKey := '';
    end
    else
        TempStr := TempStr + '|';

    AnimalList.add(TempStr);

//Hier startet jetzt die rekursive Suche!
    If (SireKey <> '') then
        InbreedCheck(SireKey, AnimalList);
    If (DamKey <> '') then
        InbreedCheck(DamKey, AnimalList);

    If StartNode then
    begin
        ...
        AnimalList.free;
        ...
    end;
end;

hoika 1. Nov 2007 06:13

Re: Memory Leak bei rekursiven Aufruf...
 
Hallo,

lade dir memcheck runter (google)
und probier es aus, indem du die Routine
in einem eigenen Programm (nicht Dll) testest.

Das "eigene Programm schreiben" könntest du dir über dUnit sparen.


Heiko

marabu 1. Nov 2007 06:43

Re: Memory Leak bei rekursiven Aufruf...
 
Hallo Niels,

du solltest PedigreeList außerhalb der rekursiven Methode instanzieren und die Erzeugung von AnimalList entfernen.

Delphi-Quellcode:
procedure XXX.InbreedCheck(subjectKey: string; PedigreeList: TStrings);
var
  SireKey, DameKey: string;
begin
  // SireKey := GetSireKey(subjectKey);
  // DameKey := GetDameKey(subjectKey);

  if PedigreeList.IndexOf(subjectKey) < 0 then
    PedigreeList.Add(subjectKey);

  if (SireKey <> '') then
    InbreedCheck(SireKey, PedigreeList);

  if (DameKey <> '') then
    InbreedCheck(DameKey, PedigreeList);
end;
Grüße vom marabu

xaromz 1. Nov 2007 07:59

Re: Memory Leak bei rekursiven Aufruf...
 
Hallo,

außerdem solltest Du Strings möglichst immer als const übergeben. Das verhindert zwar kein Memory leak, läuft aber performanter.

Gruß
xaromz

Niels14 13. Nov 2007 04:37

Re: Memory Leak bei rekursiven Aufruf...
 
Hi, ich habe jetzt den Ausloeser fuer den riesen Speicherverbrauch gefunden!
Die Zeile in der ich meine TStrings liste auf das Vorkommen eines andere Strings untersuche hat das Problem verursacht:
Code:
If pos(SireKey, AnimalList.GetText) > 0 then ...
Ich habe nun einfach die Ueberpruefung ausgelassen und der Speicher ist immer sauber wieder freigegeben worden!
Hat einer von euch eine Ahnung was der "pos" Befehl intern genau macht und wieso er soviel Speicher reserviert und nicht mehr hergibt!
Hat mir jemand vielleicht einen workaround der nicht so viel Speicher frisst?
Ist das ein bekanntes Problem? Hat jemand schon etwas aehnliches erlebt oder eine andere Moeglichkeit gefunden das zu umgehen?

jottkaerr 13. Nov 2007 06:04

Re: Memory Leak bei rekursiven Aufruf...
 
Hallo,

das Problem liegt nicht beim Aufruf von Pos() sondern von AnimalList.GetText(). Du solltest statt GetText() besser das Property Text verwenden, denn GetText() fordert neuen Speicher an und gibt einen Verweis darauf als PChar zurück. Die Freigabe dieses Speichers ist Aufgabe des aufrufenden Programmteils. (Siehe auch die Hilfe zu TStrings.GetText().)

jkr

Niels14 13. Nov 2007 20:52

Re: Memory Leak bei rekursiven Aufruf...
 
Vielen Dank fuer eure Hilfe.
Manchmal sieht man nicht das naheliegendste :wall:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz