MÜSSEN fstreams geschlossen oder gelöscht werden?



  • Hi zusammen bei mir im Hintergrund durchläuft grad mein Programm im Debug mode eine Schleife mit ca 13000 durchläufen, wo jedes mal ein fstream geöffnet wird. Ich habe das Gefühl, dass es von durchlauf zu durchlauf immer länger dauert! Ich habe bisher keine Leaks bemerkt, ich habe das Programm auch schon mit memproof und ähnlichem, Überprüft, aber es gibt keine Leaks.

    Was passiert wenn ein fstream geöffnet ist und ich öffne einen neuen? Wird dann der erste geschlossen oder überschrieben oder bleibt der als Leiche im Arbeitsspeicher liege (was ganz klar ein Leak wäre)
    Vielen Dank schon im Voraus für eure Hilfe



  • Da die STL als Bestandteil deines Compiler/IDE im Quellcode beiliegt, lässt
    sich deine Frage doch wohl am besten durch einen Blick in den Quellcode bzw.
    durch den Debugger lösen. 😉



  • Was man öffnet sollte man auch wieder schliessen.



  • Schreib mal vor jedes file.close() ein file.clear()

    Vielleicht reicht das schon, ansonsten poste doch einfach mal Deine Schleife.

    Gruss

    turing



  • Readhead! Quatsch, die streams können zwar unterschiedlich implementiert sein, aber das Verhalten ist vorgeschrieben.

    Polofreak! Wie und wann instanzierst du denn deine fstreams? Das Objekt auf dem Stack zu instanzieren ist günstiger, als auf dem Heap. Aber prinzipiell ist das Öffnen eines Filestreams halt langsam, es frisst halt Rechenzeit (Suche im Dateisystem etc.).

    Wenn ein Stream-Objekt zerstört wird, wird ja der destruktor aufgerufen, und dieser ruft natürlich die close-Methode des streams auf. Also wird immer der Filestream geschlossen.

    Weiterhin, ist es vielleicht nicht günstiger mit einem einzigen fstream-Objekt zu arbeiten? Kommt natürlih darauf an was du in der Schleife machst. Aber vielleicht kannst du ja vor der Schleife den Stream öffenen, damit den Loop durcharbeiten und nach der Schleife schliessen.



  • Artchi schrieb:

    Readhead! Quatsch, die streams können zwar unterschiedlich implementiert sein, aber das Verhalten ist vorgeschrieben.

    1.) Du bist also der Meinung das man das nicht durch einen Blick in den
    Quellcode festellen kann. 😮
    2.) Du glaubst also das jeder Compiler sich an den Standard hält. 🙄

    Willkommen in "wahren Welt" 😉



  • Redhead schrieb:

    Artchi schrieb:

    Readhead! Quatsch, die streams können zwar unterschiedlich implementiert sein, aber das Verhalten ist vorgeschrieben.

    1.) Du bist also der Meinung das man das nicht durch einen Blick in den
    Quellcode festellen kann. 😮
    2.) Du glaubst also das jeder Compiler sich an den Standard hält. 🙄

    Willkommen in "wahren Welt" 😉

    die stl implementationen müssen dem standard folgen, da code sonst nicht portabel ist(wer benutzt nen compiler dessen bibliothek nicht mit code ausm internet läuft)



  • Hi zusammen also hier mal mein Code:

    for(int i = 0; i<AnzahlFiles; i++)
    		{
    			temp = DateiNamen.GetAt(i);//DateiNamen ist ein CStringArray
    			if (itsFile.FindFile(temp))//itsfile == CFilefind
    			{
    				fstream FileBin(temp, ios::in|ios::out|ios::binary);
    				if (FileBin.is_open()) 
    				{
    					m_Wavefile = FileBin; //m_Wavefile = member fstream
    					if(!batchexport(temp,XLSFile))//eigene Funktion mit nem haufen mathematischer Berechnungen
    					{
    						MessageBox("Fehler beim Exportieren!","FEHLER");
    						break;
    					}					
    				}
    				else
    					MessageBox("File "+temp+"bereits geöffnet, kein Zugriff möglich.","FEHLER");
    			}
    			else
    				MessageBox("File not found","ERROR");
    		}
    

    Geht das irgendwie schöner? Zur Compilerfrage, ich arbeite mit MSVC da Streams aber IMHO nichts mit der MFC zu tun haben kommt die Frage hier und nicht im MFC Forum.
    Vielen dank jetzt schon für alle Infos. Ich denke ich werde nu immer nen
    .clear und
    .close machen wenn ich den Stream nicht mehr brauche.



  • otze schrieb:

    Redhead schrieb:

    Artchi schrieb:

    Readhead! Quatsch, die streams können zwar unterschiedlich implementiert sein, aber das Verhalten ist vorgeschrieben.

    1.) Du bist also der Meinung das man das nicht durch einen Blick in den
    Quellcode festellen kann. 😮
    2.) Du glaubst also das jeder Compiler sich an den Standard hält. 🙄

    Willkommen in "wahren Welt" 😉

    die stl implementationen müssen dem standard folgen, da code sonst nicht portabel ist(wer benutzt nen compiler dessen bibliothek nicht mit code ausm internet läuft)

    VC6



  • Redhead schrieb:

    VC6

    vor-standard compiler, also kein argument.



  • Und zum Topic?
    Muss ich in gezeigtem Source nun die Streams clearen und closen oder nicht? Ich hab anfangs ne Dauer für meine Berechnungen von ca. 30-50 ms und mittlerweile brauch er rund 5 Sekunden. und er ist erst bei 2000! wenn ich das mit quadratischer Steigung (so sieht es aus) weiterrechne dann schaff ich die 13000 nie! Hat jemand ne Idee wie ich es hinbekomm dass der 13000ste durchlauf gleich schnell ist wie der erste?



  • Nein brauchst du nicht selbst zu schließen. Das wird doch im Destruktor gemacht.



  • Also close brauchst du ja nicht machen, da wie bereits gesagt, das close autom. aufgerufen wird, wenn das fstream-Objekt zerstört wird. Und das passiert ja auch, da du ihn auf dem Stack instanzierst.

    Das einzige was ich nicht verstehe ist das:

    m_Wavefile = FileBin; //m_Wavefile = member fstream
    

    Im schlimmsten Fall wird hier der fstream kopiert. Kostet Zeit, das File wird auch nochmal (!) deshalb geöffnet. Hast alles doppelt gemoppelt. Übergib doch an batchexport den Filestream, als Reference und batchexport kann dann mit dem orig. fstream arbeiten.



  • Alles richtig, im Konstruktor wird der Stream geöffnet und im Destruktor geschlossen. Explizites Aufrufen von close() ist hierbei nicht notwendig.

    Hab mal davon gehört, dass unnütze Konstruktor- / Destruktoraufrufe teuer sein sollen. Ist vielleicht aber auch nur so ein Gerücht.

    Vielleicht läuft es ja ein bisschen schneller, wenn Du Dein fstream vor die Schleife packst und dann jedesmal explizit die Datei mit open() öffnest, liest und schließlich clear() und close() aufrufst.

    Was willst Du eigentlich mit der innersten If-Anweisung aussagen, ich seh da nur eine Zuweisung und einen Funktionsaufruf der gar nichts mit irgendwas ausser einem Dateinamen zu tun hat und was ist XLSFile?

    Gruss

    turing



  • das hab ich schon probiert ich brauch aber nen Zugriff auf diese Membervariable sehr oft,dadurch muss ich das lassen. Ich weiß dass ich durch diese kopieren Zeit verliere, aber das ist nicht so schlimm, das ist jetzt schon so und bei einem Durchlauf von wenigen Dateien passiert alles schnell genug! Nur irgendwo scheint er doch noch Leiche übrig zu lassen, doch ich weiß nicht wo! Seit ihr euch sicher dass ich so wie ich es gezeigt habe durch die Fstreams keine Leaks drin hab? Oder sind das nur vermutungen.
    Wann wird in meinem Source denn der Destruktor aufgerufen? Doch erst nach der schleife, oder nicht? Dann wenn ich die komplette Funktion verlasse. Oder? Sprich ich mach mir mal eben schnell 13000 Streams auf oder nicht? Bringt es was wenn ich mir den Stream vor der Schleife anleg und in der Schleife nur mit Open und Close arbeite?

    Ne ganz andere Frage ich hab grad nen Close eingebaut, nun bekomm ich folgende Meldung:

    ---------------------------
    FEHLER
    ---------------------------
    D:\acrsound\zum testen\050310_154850.wav ist kein gültiges Wav-File!
    ---------------------------
    OK
    ---------------------------

    Wieso das???



  • Das Performance-Problem kann auch eine Schicht tiefer liegen. Jeder Zugriff auf einen File (ob schreibend oder lesend), laesst das Programm mit den Betriebssystem reden - mit etwas Pech sogar ueber ein Netzwerk.

    Statt also einige tausend Male in den File zu schreiben, solltest Du das Ergebnis in eine eigene Ergebnisklasse schreiben, die schliesslich die Daten "am Stueck" in den File schreibt. Diese Klasse kann eine Verkettete Liste sein oder einfach (wenn man die STD benutzen will) auch ein Vector of String, der schliesslich in einen einzigen String verhackstueckt wird und dann am Stueck mit einem Aufruf in den FIle geschrieben.



  • OK fürs rausschreiben meiner Daten kann ich dir so ja noch recht geben, aber zum lesen leider nicht ich brauch die Werte von allen 13000 Files also muss ich auch alle 13000 öffnen oder etwa nicht??



  • guck doch im task manager nach wieviel handles geöffnet sind.

    am besten process explorer von sysinternals.com



  • Also ich hab mir das mal angeschaut und Filehandles hab ich nur eines immer offen, aber wieso kann ich nicht closen?

    Jetzt noch ein neues Phänomen, wenn ich fstream Filbin... mach dann öffnet er mir das file schön mach ich aber vor der schleife fstream filebin; und dann in der Schleife
    Filebin.Open und ich frag danach ab if (Filebin.IsOpen()) dann komm ich hier in den else Fall! Sprich er öffnet mir das File auch nicht! Woran liegt das?
    Wieso kann ich weder öffnen noch schließen?



  • Also ich bin nochmal ein Stück weiter aber kann mir einer von euch sagen wo der Unterschied zwischen denen beiden Zeilen liegt?

    FileBin.open(temp, ios::in|ios::out|ios::binary); //geht nicht EDIT: geht schon aber scheint nicht binär zu öffnen!
    fstream FileBin (temp, ios::in|ios::out|ios::binary); //geht
    

    Bei erster variante mach ich vor der Schleife fstream FileBin;
    muss ich da ohne ein File anzugeben schon sagen dass ich binär will? denn wenn ich das hier mache:

    char* pRiff = new char[4];
    	Wavefile.seekg(0,ios::beg);
    	Wavefile.read(pRiff,4);
    	if(pRiff[0] == 82 && pRiff[1] == 73 && pRiff[2] == 70 && pRiff[3] == 70)
    

    geht er mit erster variante in den else und im debug steht nur Datenmüll und bei zweitter Variante geht er mir darein!



  • oh, man dein code ist scheußlich. warum legst du ein 4 byte array auf dem heap an und warum vergleichst du jeden buchstaben einzeln und dann auch noch mit den zahlenwerten? man kann auch 'R' 'I' 'F' 'F' schreiben oder strcmp verwenden.


Anmelden zum Antworten