1 Theorie | |
→ | 1.2 Häufig auftretende Problemstellungen |
Alle angeforderten Ressourcen müssen wieder freigegeben werden. Um dies sicherzustellen, können verschiedene Strategien angewandt werden:
Die Strategien werden hier am Beispiel eines Kopier-Programmes verdeutlicht. Das Programm soll eine Quelldatei zu einer Zieldatei kopieren, falls die Quelldatei vorhanden ist und nicht leer ist.
Während des Programmlaufes fordert das Programm verschiedene Resourcen an:
Fehler können sowohl beim Anfordern der Ressourcen auftreten als auch in anderen Funktionen (z.B. Größenabfrage der Quelldatei, Einlesen der Quelldatei, Schließen der Zieldatei...).
Die drei Strategien werden hier in der main()-Funktion angewandt. Die Anwendung in anderen Funktionen ist analog mit den Unterschieden, dass dann kein exit() am Ende der Funktion steht sondern ein return und nicht der Exit-Status-Code des Programmes sondern der Rückgabewert der Funktion gesetzt wird.
Hier werden verschachtelte Anweisungen verwendet, im Beispiel verschachtelte if-Anweisungen. Jeder Folgeschritt wird nur ausgeführt, wenn der vorangegangene Schritt erfolgreich war.
Der Rückgabewert bzw. hier der Exit-Status-Code wird auf den Kennwert für "Fehler aufgetreten" initialisiert.
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { /* Die weiteren Schritte werden dann hier eingefuegt. */ } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { /* Die weiteren Schritte werden dann hier eingefuegt. */ fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* Die weiteren Schritte werden dann hier eingefuegt. */ } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { /* Die weiteren Schritte werden dann hier eingefuegt. */ } else { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ } } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { if ((uintmax_t)SIZE_MAX >= filesize) { /* Die weiteren Schritte werden dann hier eingefuegt. */ } else { /* !!! Dateigroesse zu gross fuer size_t */ } } else { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ } } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { if ((uintmax_t)SIZE_MAX >= filesize) { puffer = calloc(1, filesize); if (NULL != puffer) { /* Die weiteren Schritte werden dann hier eingefuegt. */ free(puffer); } else { /* !!! Speicherallokation fehlgeschlagen */ } } else { /* !!! Dateigroesse zu gross fuer size_t */ } } else { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ } } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { if ((uintmax_t)SIZE_MAX >= filesize) { puffer = calloc(1, filesize); if (NULL != puffer) { rdbytes = fread(puffer, 1, filesize, infile); if (filesize == (uintmax_t)rdbytes) { /* Die weiteren Schritte werden dann hier eingefuegt. */ } else { /* !!! Nicht alle Bytes eingelesen */ } free(puffer); } else { /* !!! Speicherallokation fehlgeschlagen */ } } else { /* !!! Dateigroesse zu gross fuer size_t */ } } else { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ } } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { if ((uintmax_t)SIZE_MAX >= filesize) { puffer = calloc(1, filesize); if (NULL != puffer) { rdbytes = fread(puffer, 1, filesize, infile); if (filesize == (uintmax_t)rdbytes) { outfile = fopen(argv[2], "wb"); if (NULL != outfile) { /* Die weiteren Schritte werden dann hier eingefuegt. */ if (0 != fclose(outfile)) { exc = EXIT_FAILURE; /* !!! Fehler beim Schliessen der Zieldatei */ } } else { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ } } else { /* !!! Nicht alle Bytes eingelesen */ } free(puffer); } else { /* !!! Speicherallokation fehlgeschlagen */ } } else { /* !!! Dateigroesse zu gross fuer size_t */ } } else { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ } } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex031.c Demonstrationsprogramm zur Ressourcenfreigabe. ex031 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { if ((uintmax_t)SIZE_MAX >= filesize) { puffer = calloc(1, filesize); if (NULL != puffer) { rdbytes = fread(puffer, 1, filesize, infile); if (filesize == (uintmax_t)rdbytes) { outfile = fopen(argv[2], "wb"); if (NULL != outfile) { wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes == rdbytes) { exc = EXIT_SUCCESS; } else { /* !!! Fehler beim Schreiben der Daten */ } if (0 != fclose(outfile)) { exc = EXIT_FAILURE; /* !!! Fehler beim Schliessen der Zieldatei */ } } else { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ } } else { /* !!! Nicht alle Bytes eingelesen */ } free(puffer); } else { /* !!! Speicherallokation fehlgeschlagen */ } } else { /* !!! Dateigroesse zu gross fuer size_t */ } } else { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ } } else { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ } fclose(infile); } else { /* !!! Quelldatei kann nicht gelesen werden */ } } else { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ } exit(exc); return exc; }
/** @file ex032.c Demonstrationsprogramm zur Ressourcenfreigabe ex032 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ if (3 == argc) { infile = fopen(argv[1], "rb"); if (NULL != infile) { if (0 != hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { if (0 < filesize) { if ((uintmax_t)SIZE_MAX >= filesize) { puffer = calloc(1, filesize); if (NULL != puffer) { rdbytes = fread(puffer, 1, filesize, infile); if (filesize == (uintmax_t)rdbytes) { outfile = fopen(argv[2], "wb"); if (NULL != outfile) { wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes == rdbytes) { exc = EXIT_SUCCESS; } else { /* Fehler beim Schreiben der Daten */ fputs("FEHLER: Zu wenige Bytes in Datei \"", stderr); fputs(argv[2], stderr); fputs("\" geschrieben!\n", stderr); fflush(stderr); } if (0 != fclose(outfile)) { exc = EXIT_FAILURE; /* Fehler beim Schliessen der Zieldatei */ fputs("FEHLER: Zieldatei \"", stderr); fputs(argv[2], stderr); fputs("\" nicht korrekt geschlossen!\n", stderr); fflush(stderr); } } else { /* Zieldatei nicht zum Schreiben geoeffnet */ fputs("FEHLER: Zieldatei \"", stderr); fputs(argv[2], stderr); fputs("\" nicht zum Schreiben geoeffnet!\n", stderr); fflush(stderr); } } else { /* Nicht alle Bytes eingelesen */ fputs("FEHLER: Zu wenige Bytes aus Datei \"", stderr); fputs(argv[1], stderr); fputs("\" gelesen!\n", stderr); fflush(stderr); } free(puffer); } else { /* Speicherallokation fehlgeschlagen */ fputs("FEHLER: Speicherallokation fehlgeschlagen!\n", stderr); fflush(stderr); } } else { /* Dateigroesse zu gross fuer size_t */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" ist zu gross!\n", stderr); fflush(stderr); } } else { /* Quelldatei hat Groesse 0, d.h. sie ist leer */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" hat Groesse 0!\n", stderr); fflush(stderr); } } else { /* Groesse der Quelldatei kann nicht bestimmt werden */ fputs("FEHLER: Groesse der Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" kann nicht bestimmt werden!\n", stderr); fflush(stderr); } fclose(infile); } else { /* Quelldatei kann nicht gelesen werden */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" kann nicht gelesen werden!\n", stderr); fflush(stderr); } } else { /* Falsche Anzahl an Kommandozeilenargumenten */ fputs("FEHLER: Falsche Anzahl an Kommandozeilen-Argumenten!\n", stderr); fputs("ex032 Quelldatei Zieldatei\n", stderr); fflush(stderr); } exit(exc); return exc; }
Wie zu sehen ist, wächst die Einrückungstiefe mit jeder getesteten Bedingung weiter an.
Am Ende der Funktion markiert eine einzelne Sprungmarke den
Beginn eines Code-Abschnittes zum Aufräumen. In diesem
Codeabschnitt wird jeweils getestet, welche Ressourcen erfolgreich
angefordert wurden, diese Ressourcen werden dann wieder
freigegeben.
Da mitunter Ressourcen aufeinander aufbauen, erfolgt die Freigabe
in umgekehrter Reihenfolge der Anforderung.
Der Test und die Freigabe finden für alle Variablen statt, die
Ressourcen speichern können. All diese Variablen müssen am Beginn
der Funktion auf einen Wert initialisiert werden, der "Ressource
(noch) nicht erhalten" anzeigt (z.B. alle Zeiger auf NULL).
Die einzelnen Programmschritte werden nacheinander abgearbeitet,
wenn keine Fehler auftreten. Nach Abarbeitung aller Schritte wird
der Code-Abschnitt zum Aufräumen erreicht und ebenfalls
abgearbeitet.
Tritt bei einem Schritt ein Fehler auf, wird eine Fehlerbehandlung
ausgeführt (z.B. eine Fehlermeldung ausgegeben) und anschließend
mit goto ein Sprung zur Sprungmarke für den Code-Abschnitt
zum Aufräumen durchgeführt. Dabei werden die normalerweise noch
auszuführenden nachfolgenden Schritte übersprungen.
Der Rückgabewert der Funktion bzw. hier im Beispiel der Exit-Code
des Hauptprogrammes wird zunächst auf den Wert für Misserfolg
gesetzt. Erst nach erfolgreicher Abarbeitung aller Schritte wird er
auf den Wert für Erfolg gesetzt.
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Die Schritte stehen hier. Falls in den auszufuehrenden Schritten */ /* ein Fehler auftritt, wird zu finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto finished; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != puffer) { free(puffer); } if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto finished; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto finished; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != puffer) { free(puffer); } if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto finished; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto finished; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto finished; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* finished gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != outfile) { if (0 != fclose(outfile)) { /* !!! Fehler beim Schliessen der Zieldatei */ exc = EXIT_FAILURE; } } if (NULL != puffer) { free(puffer); } if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto finished; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto finished; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto finished; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ goto finished; } /* Dateiinhalt schreiben */ wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes < rdbytes) { /* !!! Fehler beim Schreiben der Daten */ goto finished; } /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != outfile) { if (0 != fclose(outfile)) { /* !!! Fehler beim Schliessen der Zieldatei */ exc = EXIT_FAILURE; } } if (NULL != puffer) { free(puffer); } if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex035.c Demonstrationsprogramm zur Ressourcenfreigabe. ex035 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto finished; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto finished; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto finished; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ goto finished; } /* Dateiinhalt schreiben */ wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes < rdbytes) { /* !!! Fehler beim Schreiben der Daten */ goto finished; } /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != outfile) { if (0 != fclose(outfile)) { /* !!! Fehler beim Schliessen der Zieldatei */ exc = EXIT_FAILURE; } } if (NULL != puffer) { free(puffer); } if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
/** @file ex036.c Demonstrationsprogramm zur Ressourcenfreigabe. ex036 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* Falsche Anzahl an Kommandozeilenargumenten */ fputs("FEHLER: Falsche Anzahl an Kommandozeilen-Argumenten!\n", stderr); fputs("ex032 Quelldatei Zieldatei\n", stderr); fflush(stderr); goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* Quelldatei kann nicht gelesen werden */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" kann nicht gelesen werden!\n", stderr); fflush(stderr); goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* Groesse der Quelldatei kann nicht bestimmt werden */ fputs("FEHLER: Groesse der Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" kann nicht bestimmt werden!\n", stderr); fflush(stderr); goto finished; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* Quelldatei hat Groesse 0, d.h. sie ist leer */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" hat Groesse 0!\n", stderr); fflush(stderr); goto finished; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* Dateigroesse zu gross fuer size_t */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" ist zu gross!\n", stderr); fflush(stderr); goto finished; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* Speicherallokation fehlgeschlagen */ fputs("FEHLER: Speicherallokation fehlgeschlagen!\n", stderr); fflush(stderr); goto finished; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* Nicht alle Bytes eingelesen */ fputs("FEHLER: Zu wenige Bytes aus Datei \"", stderr); fputs(argv[1], stderr); fputs("\" gelesen!\n", stderr); fflush(stderr); goto finished; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* Zieldatei nicht zum Schreiben geoeffnet */ fputs("FEHLER: Zieldatei \"", stderr); fputs(argv[2], stderr); fputs("\" nicht zum Schreiben geoeffnet!\n", stderr); fflush(stderr); goto finished; } /* Dateiinhalt schreiben */ wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes < rdbytes) { /* Fehler beim Schreiben der Daten */ fputs("FEHLER: Zu wenige Bytes in Datei \"", stderr); fputs(argv[2], stderr); fputs("\" geschrieben!\n", stderr); fflush(stderr); goto finished; } /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: if (NULL != outfile) { if (0 != fclose(outfile)) { fputs("FEHLER: Datei \"", stderr); fputs(argv[2], stderr); fputs("\"\nwurde nicht komplett auf Datentraeger geschrieben!\n", stderr); fflush(stderr); exc = EXIT_FAILURE; } } if (NULL != puffer) { free(puffer); } if (NULL != infile) { fclose(infile); } exit(exc); return exc; }
Vor der Freigabe jeder Ressource muss getestet werden, ob die
Ressource-Anforderung erfolgreich war.
Für alle Ressourcen-Variablen muss eine Initialisierung auf den
Kennwert für "Ressource nicht vorhanden" erfolgen. Im Beispiel
werden daher die Zeiger infile, outfile und
puffer auf NULL initialisiert.
Bei einer Sprungmarkenkette werden die einzelnen Schritte
nacheinander abgearbeitet, wenn keine Fehler auftreten.
Für den Fall, dass Fehler auftreten, werden am Ende der Funktion
Sprungmarken mit
Name:
vereinbart.
Für den Fall, dass ein Schritt fehlschlägt, wird mit
goto Name;
zu einer Sprungmarke gesprungen, d.h. der zwischen der goto-Anweisung und der Sprungmarkendefinition stehende Code wird übersprungen. Der Code nach der Sprungmarke sorgt dann für die Freigabe aller bisher erfolgreich angeforderten Ressourcen.
Werden in nachfolgenden Schritten weitere Ressourcen angefordert, werden zusätzliche Sprungmarken vor den bereits bestehenden eingefügt.
Der zu den Sprungmarken gehörige Code kann entweder durch einen gezielten Sprung mit goto erreicht werden oder durch normale Abarbeitung.
Der Rückgabewert der Funktion bzw. hier der Exit-Status-Code wird zunächst auf einen Fehler-Kennwert initialisiert. Erst wenn alle Schritte erfolgreich absolviert wurden, wird er auf einen Erfolg-Kennwert gesetzt.
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Die Schritte stehen hier. Falls in den auszufuehrenden Schritten */ /* ein Fehler auftritt, wird zu finished oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Weitere Schritte hier. Falls in den weiteren Schritten Fehler */ /* auftreten, wird zu finished oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* close_input_file oder einer davor liegenden Sprungmarke */ /* gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Weitere Schritte hier. Falls dabei Fehler auftreten, wird zu */ /* close_input_file oder einer davor liegenden Sprungmarke */ /* gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Weitere Schritte hier. Falls in den weiteren Schritten Fehler */ /* auftreten, wird zu close_input_file oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto close_input_file; } /* Weitere Schritte hier. Falls in den weiteren Schritten Fehler */ /* auftreten, wird zu close_input_file oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto close_input_file; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto close_input_file; } /* Weitere Schritte hier. Falls in den weiteren Schritten Fehler */ /* auftreten, wird zu release_memory oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; release_memory: free(puffer); close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto close_input_file; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto close_input_file; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto release_memory; } /* Weitere Schritte hier. Falls in den weiteren Schritten Fehler */ /* auftreten, wird zu release_memory oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; release_memory: free(puffer); close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto close_input_file; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto close_input_file; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto release_memory; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ goto release_memory; } /* Weitere Schritte hier. Falls in den weiteren Schritten Fehler */ /* auftreten, wird zu close_output_file oder einer davor liegenden */ /* Sprungmarke gesprungen. */ /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_output_file: if (0 != fclose(outfile)) { /* !!! Fehler beim Schliessen der Zieldatei */ exc = EXIT_FAILURE; } release_memory: free(puffer); close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto close_input_file; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto close_input_file; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto release_memory; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ goto release_memory; } /* Dateiinhalt schreiben */ wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes < rdbytes) { /* !!! Fehler beim Schreiben der Daten */ goto close_output_file; } /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_output_file: if (0 != fclose(outfile)) { /* !!! Fehler beim Schliessen der Zieldatei */ exc = EXIT_FAILURE; } release_memory: free(puffer); close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex033.c Demonstrationsprogramm zur Ressourcenfreigabe. ex033 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* !!! Falsche Anzahl an Kommandozeilenargumenten */ goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* !!! Quelldatei kann nicht gelesen werden */ goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* !!! Groesse der Quelldatei kann nicht bestimmt werden */ goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* !!! Quelldatei hat Groesse 0, d.h. sie ist leer */ goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* !!! Dateigroesse zu gross fuer size_t */ goto close_input_file; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* !!! Speicherallokation fehlgeschlagen */ goto close_input_file; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* !!! Nicht alle Bytes eingelesen */ goto release_memory; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* !!! Zieldatei nicht zum Schreiben geoeffnet */ goto release_memory; } /* Dateiinhalt schreiben */ wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes < rdbytes) { /* !!! Fehler beim Schreiben der Daten */ goto close_output_file; } /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_output_file: if (0 != fclose(outfile)) { /* !!! Fehler beim Schliessen der Zieldatei */ exc = EXIT_FAILURE; } release_memory: free(puffer); close_input_file: fclose(infile); finished: exit(exc); return exc; }
/** @file ex034.c Demonstrationsprogramm zur Ressourcenfreigabe. ex034 Quelldatei Zieldatei */ #include "he-conf.h" #if HE_ON_WINDOWS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include <stdio.h> #if HAVE_STDLIB_H #include <stdlib.h> #endif #if HAVE_UNISTD_H #include <unistd.h> #endif #if HAVE_PROCESS_H #include <process.h> #endif #if HAVE_STDINT_H #include <stdint.h> #endif #if HAVE_LIMITS_H #include <limits.h> #endif #include "he-file.h" /** Hauptprogramm. @param argc Anzahl der Kommandozeilen-Argumente. @param argv Kommandozeilen-Argumente. @return 0 bei Erfolg, alle anderen Werte weisen auf Fehler in. */ int main(int argc, char *argv[]) { FILE *infile = NULL; /* Eingabedatei */ FILE *outfile = NULL; /* Ausgabedatei */ void *puffer = NULL; /* Puffer fuer Dateiinhalt */ uintmax_t filesize; /* Dateigroesse */ size_t rdbytes; /* Anzahl gelesene Bytes */ size_t wrbytes; /* Anzahl geschriebene Bytes */ int exc = EXIT_FAILURE; /* Exit-Status-Code */ /* Anzahl an Kommandozeilenargumenten testen */ if (3 != argc) { /* Falsche Anzahl an Kommandozeilenargumenten */ fputs("FEHLER: Falsche Anzahl an Kommandozeilen-Argumenten!\n", stderr); fputs("ex032 Quelldatei Zieldatei\n", stderr); fflush(stderr); goto finished; } /* Eingabedatei oeffnen */ infile = fopen(argv[1], "rb"); if (NULL == infile) { /* Quelldatei kann nicht gelesen werden */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" kann nicht gelesen werden!\n", stderr); fflush(stderr); goto finished; } /* Versuchen, die Groesse der Quelldatei zu bestimmen */ if (0 == hsm_et_file_pointer_size(&filesize, infile, argv[1], NULL)) { /* Groesse der Quelldatei kann nicht bestimmt werden */ fputs("FEHLER: Groesse der Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" kann nicht bestimmt werden!\n", stderr); fflush(stderr); goto close_input_file; } /* Groessentest, Wert muss positiv sein */ if (0 == filesize) { /* Quelldatei hat Groesse 0, d.h. sie ist leer */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" hat Groesse 0!\n", stderr); fflush(stderr); goto close_input_file; } /* Groessentest, Wert muss als size_t abbildbar sein */ if ((uintmax_t)SIZE_MAX < filesize) { /* Dateigroesse zu gross fuer size_t */ fputs("FEHLER: Quelldatei \"", stderr); fputs(argv[1], stderr); fputs("\" ist zu gross!\n", stderr); fflush(stderr); goto close_input_file; } /* Speicher dynamisch allozieren, Test */ puffer = calloc(1, filesize); if (NULL == puffer) { /* Speicherallokation fehlgeschlagen */ fputs("FEHLER: Speicherallokation fehlgeschlagen!\n", stderr); fflush(stderr); goto close_input_file; } /* Einlesen, Test ob vollstaendig eingelesen wurde. */ rdbytes = fread(puffer, 1, filesize, infile); if ((uintmax_t)rdbytes < filesize) { /* Nicht alle Bytes eingelesen */ fputs("FEHLER: Zu wenige Bytes aus Datei \"", stderr); fputs(argv[1], stderr); fputs("\" gelesen!\n", stderr); fflush(stderr); goto release_memory; } /* Ausgabedatei oeffnen */ outfile = fopen(argv[2], "wb"); if (NULL == outfile) { /* Zieldatei nicht zum Schreiben geoeffnet */ fputs("FEHLER: Zieldatei \"", stderr); fputs(argv[2], stderr); fputs("\" nicht zum Schreiben geoeffnet!\n", stderr); fflush(stderr); goto release_memory; } /* Dateiinhalt schreiben */ wrbytes = fwrite(puffer, 1, rdbytes, outfile); if (wrbytes < rdbytes) { /* Fehler beim Schreiben der Daten */ fputs("FEHLER: Zu wenige Bytes in Datei \"", stderr); fputs(argv[2], stderr); fputs("\" geschrieben!\n", stderr); fflush(stderr); goto close_output_file; } /* Hier wurde alles erfolgreich abgearbeitet. */ exc = EXIT_SUCCESS; close_output_file: if (0 != fclose(outfile)) { /* Fehler beim Schliessen der Zieldatei */ fputs("FEHLER: Zieldatei \"", stderr); fputs(argv[2], stderr); fputs("\" nicht korrekt geschlossen!\n", stderr); fflush(stderr); exc = EXIT_FAILURE; } release_memory: free(puffer); close_input_file: fclose(infile); finished: exit(exc); return exc; }
Im Vergleich zu verschachtelten if-Anweisungen ist der Code hier
durch generell geringere Einrückungstiefen übersichtlicher.
Nachteilig ist, dass man beim Programmieren immer den Überblich
behalten muss, zu welcher Sprungmarke im Fehlerfall gesprungen
werden muss.
Die Auswahl einer der drei Strategien ist meist Geschmackssache. Wichtig ist, dass bei Fehlern nicht wahlfrei mit return die Funktion bzw. mit exit() das ganze Programm verlassen wird. Stattdessen gibt es einen Punkt für die geordnete Rückkehr aus der Funktion am Ende der Funktion.
variable = versuche_ressource_zu_erhalten(...); if (FEHLER_KENNWERT != variable) { /* Code, der die Ressource benutzt */ ressource_freigeben(variable); } else { /* Fehlermeldung */ }eingefügt werden, zusätzlicher Code am Ende der Funktion ist nicht erforderlich.
Die strukturierte Programmierung mit verschachtelten
Programmstrukturen sollte nur benutzt werden, wenn die Anzahl
der auszuführenden Tests auf erfolgreiche Ressourcen-Anforderungen
bzw. auf aufgetretene Fehler überschaubar ist.
Mit einer Aufteilung des Codes auf mehrere Funktionen kann die
Anzahl der auszuführenden Tests innerhalb der einzelnen Funktionen
reduziert werden.
Am übersichtlichsten ist die Verwendung einer einzelnen Sprungmarke. Auch hier ist es mitunter sinnvoll, den Code auf mehrere Funktionen zu verteilen, damit kann die Länge der einzelnen Funktionen gering gehalten werden.
Die Sprungmarkenkette wird nur dann empfohlen, wenn der minimale Performancegewinn aus dem Weglassen der Initialisierung und der Tests vor der Freigabe relevant ist.
Sie können nun die Aufgabenstellungen für die Übungen 8 bis 13 bearbeiten.