AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Torrent Client - socket.sendstream mit Memory Leak
Thema durchsuchen
Ansicht
Themen-Optionen

Torrent Client - socket.sendstream mit Memory Leak

Offene Frage von "umpani"
Ein Thema von umpani · begonnen am 22. Okt 2008 · letzter Beitrag vom 24. Okt 2008
Antwort Antwort
umpani

Registriert seit: 27. Nov 2007
Ort: Essen
3 Beiträge
 
#1

Torrent Client - socket.sendstream mit Memory Leak

  Alt 22. Okt 2008, 23:21
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:
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  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
Der dazugehörige Delphi-Code:

Delphi-Quellcode:
  try
     torrent.peers.peerliste[peernr].client.Socket.SendStream(get_handshake(torrent));
  finally
  ...
  end;
Delphi-Quellcode:
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;
In den Delphihilfen steht, das "socket.sendstream" den übegebenen Stream selbst freigibt. Eine eigenhändige Freigabe verursacht eine exception.

Wie gesagt, von der Funktion her funktionieren der Code einwandfrei.

Ich hoffe ihr könnt mir weiterhelfen.

Gruß Umpani
  Mit Zitat antworten Zitat
InfixIterator

Registriert seit: 25. Nov 2007
16 Beiträge
 
#2

Re: Torrent Client - socket.sendstream mit Memory Leak

  Alt 23. Okt 2008, 17:44
Vielleicht hilft es, wenn du den Memory Stream wieder frei gibst:
  result := tmemorystream.create; Da könnte sich einiges summieren, wenn die Funktion öfter aufgerufen wird.

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...
  Mit Zitat antworten Zitat
Roachford
(Gast)

n/a Beiträge
 
#3

Re: Torrent Client - socket.sendstream mit Memory Leak

  Alt 23. Okt 2008, 22:35
Zitat von InfixIterator:
Vielleicht hilft es, wenn du den Memory Stream wieder frei gibst:
Lies bitte den Beitrag zuvor nochmal bis zum Ende. Und die Hilfe zu TCustomWinSocket.SendStream() hätte auch geholfen.

@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.
  Mit Zitat antworten Zitat
umpani

Registriert seit: 27. Nov 2007
Ort: Essen
3 Beiträge
 
#4

Re: Torrent Client - socket.sendstream mit Memory Leak

  Alt 24. Okt 2008, 00:06
Gibt es denn eine Möglichkeit, den Speicher wieder freizugeben, ohne dass ich das Programm minimiere?
  Mit Zitat antworten Zitat
InfixIterator

Registriert seit: 25. Nov 2007
16 Beiträge
 
#5

Re: Torrent Client - socket.sendstream mit Memory Leak

  Alt 24. Okt 2008, 19:38
@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?
(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
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...
  Mit Zitat antworten Zitat
Roachford
(Gast)

n/a Beiträge
 
#6

Re: Torrent Client - socket.sendstream mit Memory Leak

  Alt 24. Okt 2008, 21:49
Zitat von InfixIterator:
socket.sendstream ungleich tmemorystream
Jo, das eine ist eine Methode, das andere eine Klasse.

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.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:21 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