Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   String MemoryLeak (https://www.delphipraxis.net/153933-string-memoryleak.html)

dinosaur 20. Aug 2010 14:37

Delphi-Version: 2010

String MemoryLeak
 
FastMM meldet mir einige Memorleaks (Ansistrings), aber ich verstehe nicht, weshalb diese auftreten

logfile:
This block was allocated by thread 0xFDC, and the stack trace (return addresses) at the time was:
4047E2 [System][System.@GetMem]
407788 [System][System.@NewAnsiString]
4077D7 [System][System.@LStrFromPCharLen]
D87FE4 [TwixApi.pas][Twixapi][Twixapi.TTwixapi.GetMainEntry][1070]
77773B97 [RtlNtStatusToDosError]
77773B9C [RtlNtStatusToDosError]
75946A96 [Unknown function at InterlockedCompareExchange]
7594CC66 [Unknown function at SizeofResource]
7594CA61 [FindResourceExW]
7594CA61 [FindResourceExW]
76EA2BB4 [Unknown function at GetSysColorBrush]

The block is currently used for an object of class: AnsiString

dies ist die entsprechende stelle im Code. Zeile 1070 ist die Zuweisung des Results.

Delphi-Quellcode:
function TTwixapi.GetMainEntry(ID_MainEntry: Integer): AnsiString;
var
   pTmpStr: Array[0..1023] of AnsiChar;
begin
   if TwixGetMainentry(ID_MainEntry, @pTmpStr[0], 1024) then
   begin
      result := AnsiString(pTmpStr);
   end;
end;
eine 2. Variante resultiert ebenfalls im selben memoryleak:

Delphi-Quellcode:
function TTwixapi.GetMainEntry(ID_MainEntry: Integer): AnsiString;
var
   pTmpStr: PAnsiChar;
begin
   result := '';
   pTmpStr := AnsiStrAlloc(1024);
   pTmpStr[0] := #0;
   try
      if TwixGetMainentry(Index, ID_FollowEntry, pTmpStr, 1024) then
      begin
         result := pTmpStr;
      end;
   finally
      StrDispose(pTmpStr);
   end;
end;

auf aufgerufenen Funktionen habe ich keinen einfluss, TwixGetMainentry stammt aus einer DLL.
Kann mich jemand auf den richtigen Weg lotsen?

SirThornberry 20. Aug 2010 15:08

AW: String MemoryLeak
 
Und was passiert bei folgendem Konstrukt?
Delphi-Quellcode:
function TTwixapi.GetMainEntry(ID_MainEntry: Integer): AnsiString;
begin
  SetLength(Result, 1024);
  if not TwixGetMainentry(ID_MainEntry, @Result[1], 1024) then
    Result := '';
end;

ele 20. Aug 2010 15:30

AW: String MemoryLeak
 
Schau dir mal an in welcher Variable du den Rückgabewert der Funktion speicherst. Ich vermute das ist eine Klassen-Variable und du gibst das entsprechende Objekt nicht frei.

dinosaur 20. Aug 2010 15:51

AW: String MemoryLeak
 
vielen Dank, SirThornberry mit SetLength klappts, ich musste einfach noch zusätzlich den string bis vor #0 zusammenschneiden, sonst klappe es nachher nicht mehr mit der string concatenation..

Delphi-Quellcode:
if TwixGetMainentry(ID_MainEntry, @Result[1], 1024) then
   Result := Copy(Result, 1, Pos(#0, Result)-1)
else
   Result := '';

himitsu 20. Aug 2010 16:19

AW: String MemoryLeak
 
Das Pos+Copy kannst du weglassen und die Automatik dafür nutzen:
Delphi-Quellcode:
function TTwixapi.GetMainEntry(ID_MainEntry: Integer): AnsiString;
begin
   SetLength(Result, 1023);
   //if TwixGetMainentry(ID_MainEntry, @pTmpStr[0], 1023+1) then
   if TwixGetMainentry(ID_MainEntry, @pTmpStr[0], Length(Result)+1) then
      Result := PAnsiChar(Result)
   else
      Result := '';
end;
(ein String hat noch eine #0 hinten dran, für die PChar-Kompatibilität)

Delphi-Quellcode:
function TTwixapi.GetMainEntry(ID_MainEntry: Integer): AnsiString;
var
   TmpStr: Array[0..1023] of AnsiChar;
begin
   //if TwixGetMainentry(ID_MainEntry, @TmpStr[0], 1024) then
   if TwixGetMainentry(ID_MainEntry, @TmpStr[0], Length(TmpStr)) then
      Result := @TmpStr; // oder Result := PAnsiChar(@TmpStr)
   else
      Result := '';
end;
Nur kann ich mir nicht vorstellen, wie bei deiner 1. Variante (in Post #1) dieses Speicherleck entstehen soll. :gruebel:

DeddyH 20. Aug 2010 16:25

AW: String MemoryLeak
 
Zitat:

Delphi-Quellcode:
Length(1023)+1

:?: :gruebel:

himitsu 20. Aug 2010 16:35

AW: String MemoryLeak
 
Zitat:

Zitat von DeddyH (Beitrag 1043825)
Zitat:

Delphi-Quellcode:
Length(1023)+1

:?: :gruebel:

Ein Byte eingespart? :angle2: :zwinker:
(falls man das Copy&Paste richtig betreibt :oops: )

dinosaur 23. Aug 2010 10:34

AW: String MemoryLeak
 
Zitat:

Zitat von himitsu (Beitrag 1043821)
Nur kann ich mir nicht vorstellen, wie bei deiner 1. Variante (in Post #1) dieses Speicherleck entstehen soll. :gruebel:

Es ist mir bei beiden Varianten schleierhaft, warum ein memoryleak entsteht.. wohl irgendein problem beim referenzzähler. Aber mit setLength klappts ja :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:46 Uhr.

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