Was ist ein gutes Programmiermuster für die Verarbeitung von Rückgabewerten aus den Funktionen zum Schreiben von stdio-Dateien?

8

Ich arbeite an etwas Code, der viel

erzeugt %Vor%

Warnungen, wenn mit g ++ kompiliert, und ich frage mich über das beste Programmiermuster, um tatsächlich den Rückgabewert einer großen Anzahl von separaten sequentiellen fwrite s aufzuzeichnen und zu behandeln (dh nicht die gleiche fwrite in einer Schleife)

Sagen wir, dass der Code im Moment so aussieht:

%Vor%

Ich denke gerade über etwas wie das nach, aber ich habe möglicherweise Schwierigkeiten, den Dateizeiger aufzuräumen:

%Vor%

Ich denke, dass dieser Ansatz eindeutig besser ist als Nesting, was zu schnell zu verrückt werden würde:

%Vor%

Sicherlich gibt es bereits ein bewährtes Best-Practice-Muster für diese Art von Dingen, obwohl?

Natürlich, da ich mich hauptsächlich damit beschäftige, die Compiler-Warnungen loszuwerden, könnte ich einfach den Rückgabewert einer Dummy-Variablen zuweisen und sie ignorieren, aber ich möchte es zuerst richtig versuchen.

%Vor%

Update: Ich habe das C ++ - Tag entfernt, da dieser Code wirklich nur mit g ++ kompiliert wird. Daher werden c-basierte Lösungen benötigt, um mit dem Rest der Codebasis zu bleiben.

>     
David Dean 20.02.2009, 13:32
quelle

13 Antworten

10

Ich würde etwas in dieser Richtung tun:

%Vor%

Mit ein wenig C99 Makro Magie

%Vor%

und mit ferror() anstelle unserer eigenen Fehlerflagge, wie von Jonathan Leffler vorgeschlagen, kann dies als

geschrieben werden %Vor%

Wenn neben io-Fehlern noch andere Fehlerbedingungen vorliegen, müssen Sie sie dennoch mit einer oder mehreren Fehlervariablen verfolgen.

Auch Ihre Überprüfung gegen sizeof(blah) ist falsch: fwrite() gibt die Anzahl der geschriebenen Objekte zurück!

    
Christoph 20.02.2009, 14:02
quelle
10

Die C-Ausnahmebehandlung des armen Mannes basiert auf goto (tatsächlich ist die einzige und einzige Instanz, die NICHT schädlich ist):

%Vor%

Sie bekommen die Idee. Umstrukturieren Sie wie gewünscht (Einzel- / Mehrfachrückgaben, einzelne Bereinigung, benutzerdefinierte Fehlermeldungen usw.). Aus meiner Erfahrung ist dies das am häufigsten verwendete C-Fehlerbehandlungsmuster. Der entscheidende Punkt ist: NIEMALS STDLIB-Returncodes ignorieren, und ein guter Grund dafür (z. B. Lesbarkeit) ist nicht gut genug.

    
fbonnet 20.02.2009 13:49
quelle
2

Sie könnten eine Wrapper-Funktion schreiben

%Vor%

und ersetzen Sie dann alle Aufrufe von fwrite durch new_fwrite

    
Patrick McDonald 20.02.2009 13:49
quelle
2

Das Ignorieren von Fehlern ist eine schlechte Idee. Es ist viel besser, etwas Fieses zu tun, wie das Programm zum Absturz zu bringen, so dass zumindest etwas schief läuft, anstatt still zu verfahren. Noch besser ist die Überprüfung und Wiederherstellung von Fehlern.

Wenn Sie C ++ verwenden, können Sie einen RAII-Wrapper für die Datei * erstellen, damit er immer geschlossen wird. Sehen Sie sich std :: auto_ptr für Ideen an. Sie können dann jederzeit einen nützlichen Fehlercode oder von der Funktion zurückgeben oder eine Ausnahme auslösen und sich keine Gedanken über vergessene Aufräumobjekte machen.

    
Mr Fooz 20.02.2009 13:50
quelle
0

Sie können die Warnungen wie folgt entfernen:

%Vor%

Wenn Sie Ihre Hauptfrage ansprechen, wenn einer der fwrite () -Aufrufe fehlschlägt, würde ich annehmen, dass es keinen Sinn ergibt, fortzufahren, da die Ausgabe vermutlich beschädigt ist. In diesem Fall und wenn Sie C ++ getaggt haben, würde ich eine Ausnahme auslösen.

    
anon 20.02.2009 13:42
quelle
0

Die Verschachtelung ist schlecht und Mehrfachrückläufe sind auch nicht gut.

Ich habe das folgende Muster verwendet:

%Vor%

Ich weiß, dass es hässlich aussieht, aber es hat einen einzelnen Rückkehrpunkt, keine übermäßige Verschachtelung und ist sehr einfach zu pflegen.

    
qrdl 20.02.2009 13:44
quelle
0

Nun ... Sie könnten eine Wrapper-Funktion erstellen, die den Schreibvorgang erneut versucht, wenn sie fehlschlägt, vielleicht bis zu einer maximalen Anzahl von Wiederholungen, und Erfolg / Fehler zurückgibt:

%Vor%

Dann könnte Ihr Hauptcode als

geschrieben werden %Vor%     
unwind 20.02.2009 13:46
quelle
0

Ihre erste Lösung sieht gut aus. Gewöhnlich ist ein goto err; nützlicher, da Sie möglicherweise einen gemeinsamen Reinigungsteil benötigen (z. B. Zurückspulen zu einer bekannten Position).

Um GCC ruhig zu machen, tun Sie einfach:

%Vor%     
kmkaplan 20.02.2009 13:46
quelle
0

Warum umhüllst du das fwrite nicht in ein Writer-Objekt irgendeiner Art und wirfst eine Ausnahme, wenn fwrite () einen Fehlercode zurückgibt? Einfach zu programmieren, einfach zu bedienen, einfach zu verwalten. IMHO natürlich. :)

    
Bombe 20.02.2009 13:47
quelle
0

Vielleicht so etwas? Sie fangen die Fehler ab, ohne den Code zu unlesbar zu machen, und Sie können nach dem Ende der falschen Schleife bereinigen.

%Vor%     
Eric Petroelje 20.02.2009 13:53
quelle
0

So etwas würde funktionieren

%Vor%

Wenn Sie besorgt sind, dass Zeiger bereinigt werden, können Sie den Zeiger in eine Art Smart-Zeiger einbinden, bevor Sie Ihre fwrite's ausführen.

Wenn Sie keine intelligenten Zeiger verwenden wollen, funktioniert das zwar, aber es ist unordentlich, also würde ich zuerst die intelligente Zeigerroute ausprobieren

%Vor%     
Glen 20.02.2009 13:47
quelle
0

Eine potentiell elegante C-Lösung dafür könnte in etwa so aussehen (Warnung - ungetesteter, nicht kompilierter Code):

%Vor%

Das obige erreicht zwei Ziele gleichzeitig:

  • Rückgabewerte werden überprüft, sodass die Warnung nicht mehr angezeigt wird und Sie einen Statuscode zurückgeben können.
  • Wenn einer der fwrite () -Aufrufe fehlschlägt, werden die nachfolgenden Aufrufe aufgrund der Kurzschlussauswertung nicht ausgeführt, sodass zumindest der Dateischreibvorgang gestoppt wird, anstatt Ihnen eine potenziell beschädigte Datei zu geben, wenn der Fehlerzustand in der Mitte verschwindet die Funktion und Sie können wieder Daten schreiben

Leider sind die 'hässlichen' if (ok) Bausteine ​​notwendig, wenn Sie die Kurzschlussauswertung nicht überall verwenden wollen. Ich habe gesehen, dass dieses Muster in vergleichsweise kleinen Funktionen verwendet wird, wobei überall eine Kurzschlussbewertung verwendet wird, und ich würde denken, dass es wahrscheinlich am besten für diese spezielle Verwendung geeignet ist.

    
Timo Geusch 20.02.2009 14:10
quelle
0

Ok, da ich nach einer c Lösung suche (keine Ausnahmen), wie wäre es mit:

%Vor%

Und dann in meinem Code habe ich:

%Vor%     
David Dean 20.02.2009 14:02
quelle

Tags und Links