TFileStream & Speicherverbrauch
-
Ich speichere Daten die über eine TServerSocket reinkommen in einem TFileStream.
Läuft auch alles perfekt.
Jedoch ist mir aufgefallen das er fast genausoviel Speicher - Speicherplatz benötigt wie die Datei groß ist.
Wie kann ich das umgehen?? Ich dachte das ein TFileStream sowieso alles auf die Festplatte schriebt und nicht irgendwo in den RAM.
Bei Datein bis 50 MB gehts ja noch. Aber was mach ich dann sobald ich Cd-Images herumkopieren will???
Bitte um baldige Hilfe!!
-
Hallo,
TFileStream macht das auch. Wenn du aber Daten vom Socket einliest, die so riesig sind, so muß der Socket die Daten ja erstmal irgendwo zwischenspeichern, bevor er sie an deine Anwendung übergibt.
Und da dürfte es sich um den Speicher handeln, der im RAM belegt wird.Eine Lösung:
Übertrage große Daten in kleine "Häppchen".
-
Naja, die Daten werden ja sowieso nur in kleinen ~8kB Paketen verschickt. Den Rest erledigt eh mein Protokoll.
Oder hab ich dich da jetzt falsch verstanden??
-
Ich sollte etwas genauer werden;
Hier mal mein 'Empfangen'-code
if(fss->Size<streamsize) {int bufsize = Socket->ReceiveLength(); BYTE *Buffer = new BYTE[bufsize]; Socket->ReceiveBuf(Buffer, bufsize); fss->Position=fss->Size; fss->Write(Buffer, bufsize); } if(fss->Size==streamsize) {TFileStream *stream = new TFileStream(dateiname, fmCreate); stream->CopyFrom(fss,0); delete stream; fss->Position=0; //damit dann alles weiteres überschrieben wird fss->Size=0; ServerSocket2->Active=false; Timer11->Enabled=false; dateiname=""; streamsize=0; stringip=""; zeit=0; }
fss isrt ein Globaler TFileStream. Das ist zwar sicherlich nicht optimal aber wenn ich es anders versuch bekomm ich nur exceptions.
Jetzt bin ich gerade draufgekommen das nach dem datentransfer der speicher auch noch belegt wird.Kann mir Irgendjemand helfen das Empfangen besser zu machen bzw. mir sagen wie ich es schaffe den Speicher wieder freizugeben??
Danke im voraus!
-
Gen. ...,
Gen.d.Pz.Tr.Seb schrieb:
...mir sagen wie ich es schaffe den Speicher wieder freizugeben??
versuche doch mal, ab und zu den Stream zum Wegschreiben und Freigeben seines Puffers zu bewegen - vielleicht bringt das was:
FlushFileBuffers((HANDLE)fileStream->Handle);
-
Nope, das hilft nichts. Leider.
-
Gen....,
vielleicht hast Du ja nicht den ganzen Quellcode angegeben, aber das hier{ int bufsize = Socket->ReceiveLength(); BYTE *Buffer = new BYTE[bufsize]; Socket->ReceiveBuf(Buffer, bufsize); fss->Position=fss->Size; fss->Write(Buffer, bufsize); }
sieht mir nach einem Speicher-Leak aus. "Buffer" mußt Du auch wieder freigeben bzw. (noch besser) vorher nur einmal definieren.
Weiterhin kannst Du bei "ReceiveBuf" nicht sicher sein, daß Du tatsächlich immer "bufsize" Bytes erhältst (siehe CB-Hilfe). Das, was Du tatsächlich empfängst, ist das, was Dir "ReceiveBuf" als Rückgabewert liefert.
-
Das ist der ganze Quellcode.
Der Buffer war das Speicherleck! Hät mir nicht gedacht das die Tatsache, dass ich ein delete Buffer vergessen hab, solche Auswirkungen hat.
Aber hat ReceiveBuf mit einem Speicherleck zu tun?? Und soweit ich sehe steht in bufsize das richtige drinnen, da ich ja sonst die Dateien nicht richtig öffnen bzw. lesen könnte.
-
Gen.d.Pz.Tr.Seb schrieb:
Aber hat ReceiveBuf mit einem Speicherleck zu tun??
Nichts, das ist mir nur so nebenbei aufgefallen. ReceiveBuf gibt Dir die Anzahl der Bytes zurück, die tatsächlich in den Puffer geschrieben wurden. Und nur dieses Anzahl darst Du auch in den FileStream schreiben.
Angenommen, Deine Puffergröße ist 10 und die Größe Deiner Datei ist 25. Dann werden im Normalfall zuerst 2 Stücke von 10 Byte übertragen. Beim letzten ReceiveBuf werden aber nur die restlichen 5 übertragen. An den FileStream übergibst Du aber immer 10. Die letzten 5 Bytes in Deinem Puffer sind in diesem Fall undefniert und es landet Müll in Deiner Zieldatei.
Aber es kann Dir im Grunde jedesmal passieren, daß ReceiveBuf eine Anzahl Bytes zurückgibt, die ungleich Deiner Puffer-Größe ist - nicht nur beim letzten Aufruf. Also:int readBytes = Socket->ReceiveBuf(Buffer, bufsize); fss->Write(Buffer, readBytes);