Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Speicher wird nicht freigegeben


Stephan.Woebbeking - Di 22.05.12 10:20
Titel: Speicher wird nicht freigegeben
Hallo *,

ich habe in meinen Code mehrere Teile übernommen (müssen), die ähnlich diesem hier aussehen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
    iniFile := TIniFile.Create( ChangeFileExt( ParamStr( 0 ), '.ini' ) );
    try
      if iniFile.ValueExists( 'Configuration''DeviceAutoConnect' ) then begin
        bAutoConnect := iniFile.ReadBool( 'Configuration''DeviceAutoConnect', False );
        if bAutoConnect then begin
          actOnGetDeviceInfo.Execute;
        end;
      end;
    finally
      iniFile.Free;
    end;


Beim Programmstart werden drei von diesen Bereichen durchlaufen und am Ende bekomme ich Speicherlecks; unter anderem 1x, 2x oder 3x TIniFile, die Anzahl variiert dabei für mich weitestgehend ohne Bezug zum Programmlauf. Dabei würde ich denken, das "iniFile.Free" sorgt dafür, dass alles freigegeben wird. Die Zeile "iniFile.Free" wird auch tatsächlich angesprungen.

Wo ist mein Denkfehler?

Danke,
Stephan


Lemmy - Di 22.05.12 10:33

Hi,

seltsam... hast Du schon mal versucht die Einstellungen der Ini-Datei zu ändern, dass dieser optionale Code bei bAutoConnect=true nicht ausgeführt wird? Und das bei allen 3 Bereichen?

Grüße


Stephan.Woebbeking - Mi 23.05.12 08:14

Ne, hab ich noch nicht, aber ich weiß auch nicht, ob mir das weiterhilft? Wie gesagt, das "Free" wird auch angesprungen und ich habe die globale Suche verwendet um alle "Create" Stellen zu finden. Der Code dazwischen wird halt auch benötigt... Ich schau's mir mal an, wüsste aber gar nicht, wonach ich suchen muss, wenn das wirklich was ändert...

Moderiert von user profile iconNarses: Beiträge zusammengefasst

Also, den Bereich auszukommentieren ändert nichts an dem Verhalten. Was mir allerdings noch aufgefallen ist: Ich habe drei Bereiche die ein IniFile anlegen, die durchlaufen werden. Aber wenn nichts weiter an Nutzeraktion erfolgt, so gibt es am Ende nur EINE nicht freigegebene Instanz. Die drei Bereiche sehen so aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  if not FileIsReadOnly( ParamStr(0) ) then begin
    iniFile := TIniFile.Create( szIniFile );
    try
      if iniFile.ValueExists( 'Configuration''Language' ) then
        nActiveLanguage := iniFile.ReadInteger( 'Configuration''Language'1 )
      else
        iniFile.WriteInteger( 'Configuration''Language', nActiveLanguage );
    finally
      iniFile.Free;
    end;
  end;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
  if FAppIsStarting then begin
    // Check for device auto connection
    iniFile := TIniFile.Create( ChangeFileExt( ParamStr( 0 ), '.ini' ) );
    try
      if iniFile.ValueExists( 'Configuration''DeviceAutoConnect' ) then begin
        bAutoConnect := iniFile.ReadBool( 'Configuration''DeviceAutoConnect', False );
        if bAutoConnect then begin
          actOnGetDeviceInfo.Execute;
        end;
      end;
    finally
      iniFile.Free;
    end;
  end;



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
    nConnection := -1;
    iniFile := TIniFile.Create( ChangeFileExt( ParamStr( 0 ), '.ini' ) );
    try
      if iniFile.ValueExists( 'Configuration''Connection' ) then begin
        nConnection := iniFile.ReadInteger( 'Configuration''Connection', -1 );
        if nConnection > 3 then begin
          nConnection := -1;
        end;
      end;
    finally
      iniFile.Free;
    end;


Also einer dieser drei müsste nach meinem Verständnis ein Problem machen, aber welcher? Und warum? Oder, warum verhalten die anderen zwei sich besser? Was machen die anders?

Stephan


Lemmy - Mi 23.05.12 08:44

Hi,

user profile iconStephan.Woebbeking hat folgendes geschrieben Zum zitierten Posting springen:
Ne, hab ich noch nicht, aber ich weiß auch nicht, ob mir das weiterhilft?
...

Also einer dieser drei müsste nach meinem Verständnis ein Problem machen, aber welcher? Und warum? Oder, warum verhalten die anderen zwei sich besser? Was machen die anders?



dann tippe ich mit meiner nicht vorhandenen Glaskugel auf die Action die du ausführst. Und vermute dass hier entsprechende Anweisungen ablaufen die dazu führen, dass ein IniFile.create mehrfach ausgeführt wird, aber die Freigabe einmal weniger. Deshalb nochmal die Bitte: mach actOnGetDeviceInfo.Execute; bitte mal weg (auskommentieren) und schau ob das Verhalten weiterhin noch so ist...

Grüße


jaenicke - Mi 23.05.12 14:51

Binde FastMM4 als erste Unit im Projektquelltext (.dpr) ein und aktiviere in der Include-Datei den FullDebugMode. Dann kopierst du die beiliegende DLL in das Verzeichnis deines Programms und führst das aus. Schwupps, schon hast du Stacktraces wo die nicht freigegebenen Instanzen erzeugt wurden. ;-)


Tranx - Mi 23.05.12 17:44

Bei der ersten Prozedur rufst Du ja die Datei (Exe-Datei) selber auf. Welchen Sinn macht das? Denn die Anwendung selber ist ja keine INI-Datei (Text-Datei!)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  if not FileIsReadOnly( ParamStr(0) ) then begin
    iniFile := TIniFile.Create( szIniFile );
    try
      if iniFile.ValueExists( 'Configuration''Language' ) then
        nActiveLanguage := iniFile.ReadInteger( 'Configuration''Language'1 )
      else
        iniFile.WriteInteger( 'Configuration''Language', nActiveLanguage );
    finally
      iniFile.Free;
    end;
  end;


Paramstr(0) = Name der Anwendung mit Erweiterung und Pfad

Normalerweise ist die Anwendung beim Start als Readonly markiert, wenigstens solange, wie sie geöffnet ist.