Problem mit dem ifstream::open()



  • Das ist ein gekürztes Beispiel (deswegen steht ja auch drüber Variante 1 funktioniert). Der char* enthält den Dateinamen, wenn ich ihn abfange mit dem Debugger ist er auch korrekt. Nur aus irgendeinem Grund wird wenn ich open verwende die wchar_t* Version statt der char* Version verwendet ich habe ka warum, aber wie bekomm ich ihn dazu die char* Version zu bekommen.



  • Zeig mal die konkreten Fehlermeldungen.



  • Gibt keine. Das Programm Compiliert korrekt stürzt aber ab. ich mache mal ein konkreteres Beispiel evtl wird dann eher klar was ich meine.

    Nehmen wir mal an ich habe eine Datei die heist test.txt und befindet sich im Ordner der EXE. Nun habe ich einen char* pcFile. Der beinhaltet den namend er Datei also test.txt.

    Wenn ich jetzt folgendes mache:

    ifstream file(pcFile);
    

    Funktioniert das einwandfrei die Datei wird geöffnet und ich kann damit arbeiten.

    Wenn ich jedoch folgende variante nutze

    ifstream file;
    file.open(pcFile);
    

    Funktioniert das nicht, der Compiler akzeptiert es zwar ohne probleme allerdings stürzt das Programm dann ab, der Debugger meldet dann eine Zugriffsverletzung, obwohl die Datei da ist und mit Variante 1 auch zu öffnen geht. Nun geht es darum was da genau los ist, wieso Variante 1 geht und Variante 2 nicht obwohl sie ja eigentlich das selbe tun solten.

    So wie sich das darstellt scheint er die open version zu nehmen die einen wchar_t* mit dem Dateinamen erwartet statt die für char* und auch mit einem (char*) vor dem Zeiger bekomme ich nicht das gewünschte Ergebniss.

    Hoffe die sache ist jetzt etwas verständlicher.



  • Xebov schrieb:

    ...

    Das kann eigentlich nicht sein. Entweder, der Compiler wählt das richtige open, oder es gibt eine Fehlermeldung (beim Compilen) aufgrund eines Typkonfliktes.
    Kann es sein, dass der String, auf den Dein char* zeigt nicht korrekt terminiert wird (nullzeichen)? Oder hast Du evtl. Umlaute im Dateinamen?



  • Nullterminierung ist bei dem String korrekt. Hab die terminierung eben manuell durchgeführt und es gab keine änderung. Hab auchmal versucht den dateinamen direkt anzugeben also "test.txt" das funktionierte bei Variante 1 einwandfrei bei variante 2 ging es nicht auhc nicht mit (char*)"test.txt", ich finde das wirklich sehr merkwürdig.



  • Schmirgelt Dein Programm beim open ab, oder irgendwann später beim Schreiben?
    Probier außerdem mal den Dateinamen direkt beim open als Literal zu übergeben.
    Ich kann es mir eigentlich nicht vorstellen, dass bei einem Aufruf mit char* die wchar_t* -Variante aufgerufen wird.



  • Es schmiert direkt beim open ab.

    ifstream file("test.txt");//funktioniert
    ------------------
    ifstream file;
    file.open("test.txt");//funktioniert nicht
    -----------------
    ifstream file;
    file.open((char*)"test.txt");//funktioniert ebenfalls nicht
    

    Wenn ich Debugge sagt der Debugegr leider auch nciht viel nur bad ptr, wa smich sehr darauf schließen läst das er aus dem char* ein wchar_t* gemacht hat und der damit total veränderte dateiname ja nicht existiert.



  • Kann es sein, dass vorher irgendwas kaputt geht, weil Du z.B. über Puffergrenzen hinausschreibst?

    Benutzt Du evtl. einen Stream, der vorher schonmal benutzt wurde mehrmals? Also z.B. erst den Stream mit close schließen und dann wieder mit open öffnen?
    Wenn vor dem close irgendwas schiefgegangen ist, werden die Fehlerflags durch das close nicht wieder gelöscht. Also ggf. stream.clear() vor dem open aufrufen.

    Hast Du vielleicht einen exotischen oder komischen Compiler am Werkeln?



  • Der puffer des dateinamens hat noch mehr als genug Platz er ist sehr viel größer als der Inhalt.

    Nein das Programm benutzt den stream nur einmal. Habe eben ein Profilaktisches clear() vor das open gepackt, das brachte nichts.

    Ich nutze VC++2008 Express SP1.



  • Ich meine nicht den Puffer des Filenamens selbst, sondern irgendwelche anderen Sachen, die Du vorher machst. Oder vielleicht auch Dinge, die irgendwelche externen libs vielleicht machen.
    Anders ist das eigentlich nicht zu erklären. Visual Studio 2008 SP1 verhält sich bei Übergabe eines char-Literals an fstream::open auf jeden Fall korrekt.



  • Es funktioniert jetzt, der ifstream war Member einer Klasse, die hat in ihrem Konstruktor zeroMemory() auf sich selbst gemacht hab den ifstream zur globalen Variable gemacht und nun geht open plötzlich.



  • Xebov schrieb:

    der ifstream war Member einer Klasse, die hat in ihrem Konstruktor zeroMemory() auf sich selbst gemacht

    So was macht man ja auch nicht.



  • Oh man... 🙄



  • MFK schrieb:

    Xebov schrieb:

    der ifstream war Member einer Klasse, die hat in ihrem Konstruktor zeroMemory() auf sich selbst gemacht

    So was macht man ja auch nicht.

    Ich verstehe den Grund wieso ehrlich gesagt nicht, die Klasse soll alle ihre variablen mit dem Befehl leeren um Datenmüll vorzubeugen. ist aber gut zu wissen das der ifstream so empfindlich reagiert.

    Aber danke für die Hilfe.



  • Xebov schrieb:

    Ich verstehe den Grund wieso ehrlich gesagt nicht, die Klasse soll alle ihre variablen mit dem Befehl leeren um Datenmüll vorzubeugen. ist aber gut zu wissen das der ifstream so empfindlich reagiert.

    Es geht nicht um ifstream. Das ist grundsätzlich eine Schnapsidee.

    Du kannst nicht davon ausgehen, dass eine Klasse ordentlich initialisiert ist, wenn du ihre binäre Speicherrepräsentation komplett mit Nullen überbügelst. Mit hoher Wahrscheinlichkeit geht dabei eher etwas kaputt.

    Damit zerlegst du dir übrigens auch den VTable-Zeiger bei polymorphen Klassen.



  • Xebov schrieb:

    MFK schrieb:

    Xebov schrieb:

    der ifstream war Member einer Klasse, die hat in ihrem Konstruktor zeroMemory() auf sich selbst gemacht

    So was macht man ja auch nicht.

    Ich verstehe den Grund wieso ehrlich gesagt nicht, die Klasse soll alle ihre variablen mit dem Befehl leeren um Datenmüll vorzubeugen. ist aber gut zu wissen das der ifstream so empfindlich reagiert.

    Aber danke für die Hilfe.

    Alle Klassen, die interne Zustände halten, z.B. Pointer auf Heap-Objekte oder irgendwelche Stati reagieren "empfindlich" auf sowas.

    Instanzen von Standard-Libarary-Klassen dürftest Du damit sicher ins Nirvana der undefinierten Zustände bomben.

    Zum setzen von Klassen auf definierte Zustände gibt es Initialisiererlisten und ggf. den Rumpf der Konstruktoren. Aber ZeroMemory auf die Klasse anzuwenden ist mit Sicherheit eine schlchte Idee. Das kann man nur machen, wenn die Klasse ausschließlich POD-Typen enthält.



  • Also kurz gesagt lieber ein paar Zeilen mehr tippen und die Variablen einzelln Nullen?



  • zeroMemory()

    Damit machst du alles kaputt, was der Konstruktor anlegt, also auch die virtuelle Methodentabelle, interne Informationen, Metainformation. Keine gute Idee, nimm lieber Initialisierungslisten.



  • Xebov schrieb:

    Also kurz gesagt lieber ein paar Zeilen mehr tippen und die Variablen einzelln Nullen?

    Nicht nullen, sondern mit einem gültigen Wert initialisieren! Die Arbeitsweise mit ZeroMemory() oder memset() ist eher C und für die dortigen PODs angebracht. In C++ hat das meistens nichts zu suchen!

    Irgendwelche undefinierten Laufzeitauswirkungen wegen Schreibfaulheit in Kauf zu nehmen hat sich zumindest selten bewährt. Nimm wie gesagt Initialisierungslisten.


Anmelden zum Antworten