Erstellen einer neuen Datei, die Rennbedingungen vermeidet

9

Ich muss eine C ++ - Routine entwickeln, die diese scheinbar triviale Aufgabe ausführt: Erzeuge eine Datei nur, wenn sie nicht existiert, sonst tue nichts / erhebe einen Fehler.

Da ich Race Conditions vermeiden muss, möchte ich das Prinzip "Bitte Vergebung nicht Erlaubnis" verwenden (dh den beabsichtigten Vorgang versuchen und überprüfen, ob es erfolgreich war, im Gegensatz zur Überprüfung der Vorbedingungen), was meines Wissens nach ist die einzige robuste und portable Methode für diesen Zweck [Wikipedia-Artikel] [ein Beispiel mit getline] .

Trotzdem konnte ich in meinem Fall keinen Weg finden, es zu implementieren. Das Beste, was ich mir vorstellen konnte, ist ein fstream in app mode (oder fopen ing mit "a" ) zu öffnen, die Ausgabeposition mit tellp (C ++) oder ftell (C) zu prüfen und abzubrechen wenn diese Position nicht Null ist. Dies hat jedoch zwei Nachteile, nämlich dass, wenn die Datei existiert, sie gesperrt wird (wenn auch für eine kurze Zeit) und ihr Änderungsdatum geändert wird.

Ich habe andere mögliche Kombinationen von ios_base::openmode für fstream , sowie die mode Zeichenketten von fopen geprüft, aber keine Option gefunden, die meinen Anforderungen entsprach. Die weitere Suche in den C- und C ++ - Standardbibliotheken sowie im Boost-Dateisystem erwies sich als unfruchtbar.

Kann jemand auf eine Methode hinweisen, um meine Aufgabe auf eine robuste Art und Weise auszuführen (keine Nebeneffekte, keine Race Conditions), ohne auf OS-spezifische Funktionen angewiesen zu sein? Mein spezifisches Problem ist in Windows, aber tragbare Lösungen würden bevorzugt.

EDIT : Die Antwort von BitWhistler löst das Problem für C-Programme vollständig. Dennoch bin ich erstaunt, dass keine C ++ idiomatische Lösung zu existieren scheint. Entweder benutzt man open mit dem Attribut O_EXCL , wie es von Andrew Henle vorgeschlagen wurde, das jedoch Betriebssystem-spezifisch ist (in Windows scheint das Attribut _O_EXCL mit einem zusätzlichen Unterstrich [MSDN] ) oder man kompiliert separat eine C11-Datei und verknüpft sie mit dem C ++ - Code. Darüber hinaus kann der erhaltene Dateideskriptor nicht in einen Strom umgewandelt werden, außer bei nicht standardmäßigen Erweiterungen (z. B. GCCs __gnu_cxx::stdio_filebuf ). Ich hoffe, dass eine zukünftige Version von C ++ das "x" Subattribut und möglicherweise auch einen entsprechenden ios:: Modifikator für Dateiströme implementiert.

    
Alberto M 29.02.2016, 10:12
quelle

1 Antwort

3

Der neue C-Standard (C2011, der nicht Teil von C ++ ist) fügt einen neuen Standardunterspezifikator ("x") hinzu, der an jeden "w" Spezifizierer angehängt werden kann (um "wx", "wbx", " w + x "oder" w + bx "/" wb + x "). Dieser Unterspezifikator erzwingt, dass die Funktion fehlschlägt, wenn die Datei existiert, anstatt sie zu überschreiben.

Quelle: Ссылка

    
BitWhistler 29.02.2016, 11:19
quelle

Tags und Links