Ein Bug in GetLastError() in Verbindung mit ofstream?



  • Hallo,

    ich öffne eine Datei zu schreiben, und frage danach mit GetLastError() einen eventuellen Fehler ab. Die Datei soll wenn es sie noch nicht gibt neu engelegt werden, sonst werden die Daten an das Ende der Datei angehängt. Der eventuelle Fehler wird dann mit FormatMessage() dem Benutzer angezeigt.
    Das mache ich im Prinzip so:

    ofstream Reportfile;
    
    Reportfile.open("Dateiname", ios::app | fmShareExclusive);
    LastErrCode = GetLastError();
    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, LastErrCode, 0, msg, 256, NULL );
    

    GetLastError gibt hier als Fehlercode 183 (0xB7) zurück. Was letztendlich durch Formatmessage in "Eine Datei kann nicht erstellt werden wenn sie bereits vorhanden ist." angezeigt wird. Der nachfolgende Schreibvorgang wird korrekt durchgeführt.

    Ob ich die Datei mit ios::app oder ios::ate öffne, oder ob ich das fmShareExclusive benutze oder nicht macht keinen Unterschied.

    Da open() mit ios::app problemlos in beiden Fällen (neue Datei bzw. Daten anhängen) funktioniert, erschliesst sich mir der Sinn des Fehlers in GetLastError nicht ganz. Meiner Meinung dürfte hier kein Fehler angezeigt werden, da ja die letzte Operation = "Datei zum Daten anhängen öffnen" korrekt ausgeführt werden kann.

    Ist das jetzt tatsächlich ein Bug in C++, oder wende ich das nur falsch an? Ich könnte ja den Fehler 0xB7 einfach ignorieren, aber schön ist das ja nicht.

    Grüße,
    Jochen



  • Ich glaube ehrlichgesagt nicht, dass GetLastError() (WinAPI) und ofstream (Standard-C++) sonderlich gut zusammenarbeiten.

    BTW:
    Woher zum Geier kommt fmShareExclusive und was hat das bei den ios-Flags zu suchen? Bzw, wo steht dass man proprietäre Flags mit denen der Standardbibliothek mischen sollte?



  • fmShareExclusive kenn ich nur aus der TFileStream-Klasse von Borland. Wie das hier in ofstream reinpassen soll weiß ich auch nicht.
    Was für ein Compiler ist das denn?



  • Braunstein schrieb:

    fmShareExclusive kenn ich nur aus der TFileStream-Klasse von Borland. Wie das hier in ofstream reinpassen soll weiß ich auch nicht.
    Was für ein Compiler ist das denn?

    Borland Builder 6.0

    Das fmShareExclusive funktioniert auf jeden Fall damit. Genauso wie GetLastError() mit anderen Fehlern funktioniert. Deshalb wundert mich es, dass ein Fehler angezeigt wird, wo keiner ist.

    Grüße,
    Jochen

    Edit: wenn wir jemand was passenderes als das fmShareExclusive mit gleicher Funktionalität hat, nur her damit 😉



  • Das es compiliert wird, bedeutet nicht, das es auch so funktioniert. Der Compiler wird wohl die beiden Werte einfach als int (oder ähnlich) interpretieren und dann per logisches oder verknüpfen. Keine Ahnung was da raus kommt aber mit Sicherheit nicht das was du willst. GetLastError hat hier auch nichts zu suchen. Der Fehlerwert wird hier weder von ofstream noch von TFileStream gesetzt.
    Was willst du eigentlich erreichen?



  • Braunstein schrieb:

    Was willst du eigentlich erreichen?

    Ich will:
    - wenn ich die Datei geöffnet habe, darf kein anderer etwas mit dieser Datei anfangen können. (deshalb das fmSharedExclusive, was wie gesagt bei mir auch funktioniert)
    - Wenn die Datei nicht geöffnet werden kann, z.B. weil sie gerade von jemand anders benutzt wird, oder wenn sie generell schreibgeschützt ist, eine Meldung im Klartext für den Benutzer. Ich habe in der Hilfe zu fstream absolut keinen Hinweis gefunden, wie das damit gehen soll, nur den Hinweis auf badbit, goodbit usw.

    Jochen



  • GetLastError funktioniert schon, _nur_ bezieht sich GetLastError() auf Fehler die beim Aufrufen von Winapi-Funktionen passiert und ist nur so lange gültig wie keine andere aufgerufen wurde. Wieviele Winapi-Funktionen ofstream intern aufruft kannst du nicht wissen und folglich kannst du dich auf GetLastError nicht verlassen.
    Ob die Datei erstellt werden konnte, lässt sich mit good() feststellen.
    => ofstream out("bla"); if(!out){ /*error handling*/ }



  • Ergänzung:
    Wenn du sowas spezifisches haben möchtest, dann verwende direkt die Winapi-Funktionen für Dateihandling. Sowas geht weit über die Möglichkeiten von den file-streams hinaus (du kannst dir aber leicht einen eigenen file-stream schreiben der sowas beherrscht).



  • Ich hab grad mal in den Sources von fstream des BCB6 nachgeschaut. Hier wird anscheinend CreateFile aus der WinAPI verwendet (bei 32Bit-Windows und ohne CygWin). In diesem Fall wäre es vernünftig eben diese Funktion zu verwenden oder eben BCB-spezifisch TFileStream.



  • Danke, ich sehe mir das mal an.

    Jochen


Anmelden zum Antworten