Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Kann das Speicherleck nicht finden... (https://www.delphipraxis.net/59464-kann-das-speicherleck-nicht-finden.html)

BenTech 22. Dez 2005 19:28


Kann das Speicherleck nicht finden...
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe ein Programm geschrieben, das IPs anpingt. Für jeden Ping wird ein Thread erstellt. Ich stelle jedoch fest, dass bei jeder Threaderstellung und Terminierung 16 kByte verloren gehen.
Ich kann jedoch nicht nachvollziehen, wo das Speicherleck ist.

Hier der Aufruf des Threads...
Delphi-Quellcode:
IpWatchList[nowIPIndex].IPThread := TMyThreads.Create(true);
IpWatchList[nowIPIndex].IPThread.InetAddress := png_IP;
IpWatchList[nowIPIndex].IPThread.TimeOut    := settings.TimeOut;
IpWatchList[nowIPIndex].IPThread.Index      := nowIPIndex;
IpWatchList[nowIPIndex].IPThread.Resume;
So wird der Thread dann geschlossen...
Delphi-Quellcode:
procedure TForm1.UpdateIPView(Online : Boolean; Index : Integer);
begin
  //IpWatchList[Index].IPThread.FreeOnTerminate := true;
  IpWatchList[Index].IPThread.Terminate;
  if Online then
  begin
   //...
  end
  else
  begin
   //...
  end;
end;
Nach Terminate wird auch Speicher freigegeben. Jedoch weniger als zuvor reserviert wurde.

Im Thread geschieht folgendes...
Delphi-Quellcode:
procedure TMyThreads.Execute;
begin
  Online := Ping(InetAddress,TimeOut);
  UpdateMain;
end;

function TMyThreads.Ping(IPAddress : string; IPTimeOut : Integer) : boolean;
var
 Handle : THandle;
 InAddr : IPAddr;
 DW : DWORD;
 rep : array[1..128] of byte;
begin
  Result := false;
  Handle := IcmpCreateFile;
  if Handle = INVALID_HANDLE_VALUE then
   Exit;
  TranslateStringToTInAddr(InetAddress, InAddr);
  DW := IcmpSendEcho(Handle, InAddr, nil, 0, nil, @rep, 128, TimeOut);
  Result := (DW <> 0);
  IcmpCloseHandle(Handle);
end;

procedure TMyThreads.UpdateMain;
begin
  Form1.UpdateIPView(Online,Index);
end;
Zum Pingen benutze ich die Unit "raw_ping".
Vielen Dank schonmal für eure Hilfe :).

BenTech 22. Dez 2005 23:53

Re: Kann das Speicherleck nicht finden...
 
Soo, habe das Leck jetzt einschränken können. Es befindet sich eindeutig in der Ping-Funktion. Wenn ich diese aus dem Programm entferne, verschwindet das Leck.

Also scheint hier irgendwo in der "raw_ping.pas" etwas nicht ganz sauber freigegeben zu werden...
Delphi-Quellcode:
function Ping(InetAddress : string; TimeOut : Integer) : boolean;
var
 Handle : THandle;
 InAddr : IPAddr;
 DW : DWORD;
 rep : array[1..128] of byte;
begin
  result := false;
  Handle := IcmpCreateFile;
  if Handle = INVALID_HANDLE_VALUE then
   Exit;
  TranslateStringToTInAddr(InetAddress, InAddr);
  DW := IcmpSendEcho(Handle, InAddr, nil, 0, nil, @rep, 128, 0);
  Result := (DW <> 0);
  IcmpCloseHandle(Handle);
end;
Die Unit enthält natürlich noch ein paar andere Funktionen, in denen sich das Leck befinden könnte.
Ich hoffe, ich befinde mich jetzt nicht auf der falschen Fährte ;). Über Hinweise würde ich mich sehr freuen :)

Christian Seehase 23. Dez 2005 10:19

Re: Kann das Speicherleck nicht finden...
 
Moin BenTech,

wie sieht denn TranslateStringToTInAddr aus?

BenTech 23. Dez 2005 15:58

Re: Kann das Speicherleck nicht finden...
 
Hi,
hier die Prozedur...

Delphi-Quellcode:
procedure TranslateStringToTInAddr(AIP: string; var AInAddr);
var
  phe: PHostEnt;
  pac: PChar;
  GInitData: TWSAData;
begin
  WSAStartup($101, GInitData);
  try
    phe := GetHostByName(PChar(AIP));
    if Assigned(phe) then
    begin
      pac := phe^.h_addr_list^;
      if Assigned(pac) then
      begin
        with TIPAddr(AInAddr).S_un_b do begin
          s_b1 := Byte(pac[0]);
          s_b2 := Byte(pac[1]);
          s_b3 := Byte(pac[2]);
          s_b4 := Byte(pac[3]);
        end;
      end
      else
      begin
        raise Exception.Create('Error getting IP from HostName');
      end;
    end
    else
    begin
      raise Exception.Create('Error getting HostName');
    end;
  except
    FillChar(AInAddr, SizeOf(AInAddr), #0);
  end;
  WSACleanup;
end;
Zum besseren Verständnis hier noch der Header der Unit...
Delphi-Quellcode:
unit raw_ping;

interface
uses
  Windows, SysUtils, Classes;

type
  TSunB = packed record
    s_b1, s_b2, s_b3, s_b4: byte;
  end;

  TSunW = packed record
    s_w1, s_w2: word;
  end;

  PIPAddr = ^TIPAddr;
  TIPAddr = record
    case integer of
      0: (S_un_b: TSunB);
      1: (S_un_w: TSunW);
      2: (S_addr: longword);
  end;

 IPAddr = TIPAddr;

function IcmpCreateFile : THandle; stdcall; external 'icmp.dll';
function IcmpCloseHandle (icmpHandle : THandle) : boolean; stdcall; external 'icmp.dll'
function IcmpSendEcho (IcmpHandle : THandle; DestinationAddress : IPAddr;
           RequestData : Pointer; RequestSize : Smallint;
           RequestOptions : pointer;
           ReplyBuffer : Pointer;
           ReplySize : DWORD;
           Timeout : DWORD) : DWORD; stdcall; external 'icmp.dll';

BenTech 30. Dez 2005 21:36

Re: Kann das Speicherleck nicht finden...
 
Habe das Problem aus lauter Verzweiflung jetzt folgendermaßen "gelöst"...

Delphi-Quellcode:
procedure TMyThreads.Execute;
begin
 Repeat
  if not paused then
  begin
   Online := Ping(InetAddress,TimeOut);
   Synchronize(UpdateMain);
  end;
  Sleep(300);
 Until Terminated;
end;
Ich verhindere, dass der Thread terminiert, indem ich eine Endlosschleife hineinpacke. Ausgeführt wird der Ping nur, wenn "paused" false ist. Nach der Schleife habe ich ein Sleep eingebaut, damit die CPU nicht unnötig belastet wird.

Jetzt tritt das Leck nichtmehr auf, da die Threads bestehen bleiben.

Falls jemand eine elegantere Lösung haben sollte, oder wenn jemand das Speicherleck doch noch finden sollte, wäre ich natürlich sehr dankbar ;)

Ansonsten wünsche ich noch einen guten Rutsch ins neue Jahr :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:54 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