![]() |
Torrent Client - socket.sendstream mit Memory Leak
Hallo zusammen,
ich habe versuche jetzt schon mehrere Tage lang ein Memory Leak herauszufinden. Aber nichts klappt bis jetzt. Ich schreibe ein Programm, das mit anderen Torrent-Clients kommunizieren soll. Dafür werden die einzelnen TCP-Packete in Stream bereitsgestellt und über die Socket-komponente verschickt. Klappt auch alles. Allerdings verbraucht das Programm immer mehr Speicher. Mittels FastMM4 habe ich jetzt einige Problemstellen herausgefunden. Aber eine Lösung habe ich noch nicht gefunden. Wenn ich übrigens das Programm minimiere und wieder maximiere ist der unnötige Speicherbereich wieder freigegeben (natürlich nur um dann direkt wieder zu wachsen), Hier ist z.B. ein Auszug aus der FastMM Log Datei. An der Stelle, die FastMM bezeichet, erstellt dasProgramm einen Torrent-Handshake und versendet diese zu einem TCPServer.
Code:
Der dazugehörige Delphi-Code:
A memory block has been leaked. The size is: 8356
This block was allocated by thread 0xD18, and the stack trace (return addresses) at the time was: 402EE2 [system.pas][System][@GetMem][2648] 4241CF [classes.pas][Classes][TMemoryStream.SetCapacity][5591] 424335 [classes.pas][Classes][TMemoryStream.Write][5639] 4C698A [sendestreams.pas][sendestreams][get_handshake][45] 4C7C2C [peerconnect.pas][peerconnect][TPeerconnect.torrent_verbindung_aufbauen][467] 4C7B2D [peerconnect.pas][peerconnect][TPeerconnect.Execute][410] 42A985 [classes.pas][Classes][ThreadProc][9866] 404A7E [system.pas][System][ThreadWrapper][12127] 7C80B683 [Unknown function at GetModuleFileNameA] The block is currently used for an object of class: Unknown The allocation number is: 87562 Current memory dump of 256 bytes starting at pointer address 7FBE41F0: 13 42 69 74 54 6F 72 72 65 6E 74 20 70 72 6F 74 6F 63 6F 6C 00 00 00 00 00 00 00 00 87 69 7F 14 D6 F5 33 9C BC FE 57 70 E3 50 0D 5D 0B 7D 8C FB 41 5A 32 35 30 30 42 54 30 30 30 30 30 30 30 30 30 30 30 30 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 . B i t T o r r e n t p r o t o c o l . . . . . . . . ‡ i . Ö õ 3 µ Ÿ þ W p ã P . ] . } © û A Z 2 5 0 0 B T 0 0 0 0 0 0 0 0 0 0 0 0 € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € €
Delphi-Quellcode:
try
torrent.peers.peerliste[peernr].client.Socket.SendStream(get_handshake(torrent)); finally ... end;
Delphi-Quellcode:
In den Delphihilfen steht, das "socket.sendstream" den übegebenen Stream selbst freigibt. Eine eigenhändige Freigabe verursacht eine exception.
function get_handshake(input:ttorrent):tstream;
var pstrlen:byte; pstr:string; reserved:integer; infohashhex:string[40]; infohash:array[1..20] of byte; peer_id:string[20]; i,int:integer; s:string; begin result := tmemorystream.create; infohashhex := input.infohashhex; infohashhex := uppercase(infohashhex); for i := 1 to 20 do begin s := ''; s := s + infohashhex[i*2-1]; s := s + infohashhex[i*2]; infohash [i] := hextoint(s); end; pstrlen := 19; result.Write(pstrlen,1); pstr := 'BitTorrent protocol'; schreibe_string_in_stream(result,pstr); reserved := 0; result.Write(reserved,sizeof(reserved)); result.Write(reserved,sizeof(reserved)); result.Write(infohash,20); peer_id := 'AZ2500BT000000000000'; schreibe_string_in_stream(result,peer_id); result.Seek(0,soFromBeginning); end; Wie gesagt, von der Funktion her funktionieren der Code einwandfrei. Ich hoffe ihr könnt mir weiterhelfen. Gruß Umpani |
Re: Torrent Client - socket.sendstream mit Memory Leak
Vielleicht hilft es, wenn du den Memory Stream wieder frei gibst:
Delphi-Quellcode:
Da könnte sich einiges summieren, wenn die Funktion öfter aufgerufen wird.
result := tmemorystream.create;
Du musst auch aufpassen, falls der Handshake nur einmal ausgeführt werden soll, dass die Funktion auch nur einmal aufgerufen wird. Vielleicht liegt auch ein Fehler in der Prozedur schreibe_string_in_stream immerhin wird die auch zweimal aufgerufen... |
Re: Torrent Client - socket.sendstream mit Memory Leak
Zitat:
@umpani: Der Code ist so in Ordnung. Und soweit wäre vllt. wirklich mal die schreibe_string_in_stream() Methode schön zu betrachten. Und da der Speicher beim minimieren verkleinert wird, zeigt, dass es wohl nicht unbedingt um ein Speicherleck handelt sondern eher um schlechten Code, der den Speichermanager zur Verzweiflung bringt. FastMM4 ist schon wirklich gut sowas auszugleichen, aber anscheinend schafft er es nicht ganz. Beispiele dafür ist z.B. schon dein Code zum HexDump: Du baust den String einzeln in der Schleife zusammen und erweiterst ihn jedesmal. Für den Speichermanager und für die Effektivität wäre es deutlich besser vor der Schleife mit SetLength() den String zu setzen und dann die Hexdumps direkt in den String zu zuweisen. |
Re: Torrent Client - socket.sendstream mit Memory Leak
Gibt es denn eine Möglichkeit, den Speicher wieder freizugeben, ohne dass ich das Programm minimiere?
|
Re: Torrent Client - socket.sendstream mit Memory Leak
@Roachford socket.sendstream ungleich tmemorystream
Das eine sind Streams von Sockets das andere Streams im Arbeitsspeicher. (Sockets kommen in dieser Funktion eh nicht direkt vor...) Der übergebene Stream im Socket mag zwar freigegeben werden, doch wie sieht es in der Funktion aus? :P (Ich denke die Daten bleiben deswegen im Arbeitsspeicher, da sie nicht sauber gelöscht werden. Erst nach einer Minimierung fällt dem Rechner auf, das die Funktion schon längst abgehackt ist und gibt den Speicher frei.) @umpani ich habe echt noch nie jemanden gesehen, der ein result so misbraucht wie du :D Ich hätte anstatt des results eine Variable genommen und erst beim zurückgeben des Funktionswertes die Variable ans Result gehängt. (So könnte man die Variable auch noch Freigeben...) Keine Ahnung ob es hilft, aber ein Versuch wäre es Wert und der Code den man ändern müsste ist ja nicht alzu lang. Edit: evtl. könnte eine globale Variable mit tmemorystream das Problem abschaffen, da nur eine erstellt wird und benutzt wird. So würde nicht immer wieder neuer Speicher im Arbeitsspeicher reserviert werden. Jedoch könnte es aber zu massiven Probleme kommen, wenn du Threads benutzt... |
Re: Torrent Client - socket.sendstream mit Memory Leak
Zitat:
Aber mir ist eben bewusst geworden, dass es sich nicht um TCustomWinSocket Nachfahren handelt. Ich hatte mich auf TServerSocket und TClientSocket bezogen. Von daher sind meine Aussagen hinfällig, da nicht passend. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:38 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