Systemnahe Programmierung in C/C++ Fehlerbehandlung, Internationalisierung und Programmende Knut Stolze stolze@informatik.uni-jena.de Lehrstuhl für Datenbanken und Informationssysteme Fakultät für Mathematik und Informatik 2006 11 01 Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 1 / 36
Agenda 1 Fehlerbehandlung Grundsatz Mechanismen zur Fehlererkennung Tipps & Hinweise 2 Internationalisierung Internationalisierung vs. Lokalisierung X/Open Message Catalogs GNU gettext 3 Programmende 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 2 / 36
Outline 1 Fehlerbehandlung Grundsatz Mechanismen zur Fehlererkennung Tipps & Hinweise 2 Internationalisierung Internationalisierung vs. Lokalisierung X/Open Message Catalogs GNU gettext 3 Programmende 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 3 / 36
Grundsatz beim Programmieren Jeder(!) Funktionsaufruf kann Fehler/Warnungen produzieren. = Also ist nach jedem Funktionsaufruf auf Fehler zu prüfen. (Ausnahmen bestätigen die Regel.) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 4 / 36
Grundsatz beim Programmieren Jeder(!) Funktionsaufruf kann Fehler/Warnungen produzieren. = Also ist nach jedem Funktionsaufruf auf Fehler zu prüfen. (Ausnahmen bestätigen die Regel.) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 4 / 36
Grundsatz beim Programmieren Jeder(!) Funktionsaufruf kann Fehler/Warnungen produzieren. = Also ist nach jedem Funktionsaufruf auf Fehler zu prüfen. (Ausnahmen bestätigen die Regel.) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 4 / 36
Fehler von Systemfunktionen Alle Systemfunktionen geben Fehlerinformationen zurück, z. B. strchr NULL-Zeiger fopen NULL-Zeiger malloc NULL-Zeiger strtol 0 shmget -1 Zusätzliche Informationen werden über errno (vom Typ int) an Anwendung übermittelt Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 5 / 36
errno Header <errno.h> muss eingebunden werden Wird von keiner Systemfunktion auf 0 gesetzt, aber jede Funktion kann potentiell errno ändern errno in Fehlerbehandlung sichern bzw. Kopie verwenden Wenn Funktion 1 als valides Ergebnis liefern kann errno auf 0 setzen vor Funktionsaufruf errno ist keine explizit deklarierte (globale) Variable, aber modifiable lvalue Wäre nicht re-entrant & thread-safe Abhängig von Plattform und Implementierung, z. B. von libc Linux/Cygwin: Als Macro implementiert: #define errno (* errno_location()) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 6 / 36
errno Header <errno.h> muss eingebunden werden Wird von keiner Systemfunktion auf 0 gesetzt, aber jede Funktion kann potentiell errno ändern errno in Fehlerbehandlung sichern bzw. Kopie verwenden Wenn Funktion 1 als valides Ergebnis liefern kann errno auf 0 setzen vor Funktionsaufruf errno ist keine explizit deklarierte (globale) Variable, aber modifiable lvalue Wäre nicht re-entrant & thread-safe Abhängig von Plattform und Implementierung, z. B. von libc Linux/Cygwin: Als Macro implementiert: #define errno (* errno_location()) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 6 / 36
errno Header <errno.h> muss eingebunden werden Wird von keiner Systemfunktion auf 0 gesetzt, aber jede Funktion kann potentiell errno ändern errno in Fehlerbehandlung sichern bzw. Kopie verwenden Wenn Funktion 1 als valides Ergebnis liefern kann errno auf 0 setzen vor Funktionsaufruf errno ist keine explizit deklarierte (globale) Variable, aber modifiable lvalue Wäre nicht re-entrant & thread-safe Abhängig von Plattform und Implementierung, z. B. von libc Linux/Cygwin: Als Macro implementiert: #define errno (* errno_location()) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 6 / 36
errno Header <errno.h> muss eingebunden werden Wird von keiner Systemfunktion auf 0 gesetzt, aber jede Funktion kann potentiell errno ändern errno in Fehlerbehandlung sichern bzw. Kopie verwenden Wenn Funktion 1 als valides Ergebnis liefern kann errno auf 0 setzen vor Funktionsaufruf errno ist keine explizit deklarierte (globale) Variable, aber modifiable lvalue Wäre nicht re-entrant & thread-safe Abhängig von Plattform und Implementierung, z. B. von libc Linux/Cygwin: Als Macro implementiert: #define errno (* errno_location()) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 6 / 36
errno (cont.) Jeder Thread eines Prozesses hat eigene errno Definitionen der Fehlercodes in /usr/include/errno.h, z. B. #define EPERM #define ENOENT #define ESRCH #define EINTR #define EIO 1 // Operation not perm. 2 // No such file or dir 3 // No such process 4 // Interrupted call 5 // I/O error Fehlercodes können systemabhängig sein Immer Macros wie EPERM etc. verwenden Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 7 / 36
strerror et al. strerror bildet Fehlercode (errno) auf Text ab Aktuelle Locale wird verwendet Nutzt globalen Systempuffer String sollte nicht direkt modifiziert werden; kann Konstante sein String in Speicherblock der Anwendung kopieren Wird nie von Systemfunktionen selbst aufgerufen strerror_r sehr ähnlich zu strerror Nutzt von Anwendung bereitgestellter Puffer Ist thread-safe perror schreibt Meldung auf Standardfehlerausgabe (stderr) NULL-Zeiger oder leerer String: Ergebnis von strerror() wird ausgegeben In Bibliotheken üblicherweise nicht sehr brauchbar Späterer Einsatz nicht klar; Existenz von stderr nicht gesichert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 8 / 36
strerror et al. strerror bildet Fehlercode (errno) auf Text ab Aktuelle Locale wird verwendet Nutzt globalen Systempuffer String sollte nicht direkt modifiziert werden; kann Konstante sein String in Speicherblock der Anwendung kopieren Wird nie von Systemfunktionen selbst aufgerufen strerror_r sehr ähnlich zu strerror Nutzt von Anwendung bereitgestellter Puffer Ist thread-safe perror schreibt Meldung auf Standardfehlerausgabe (stderr) NULL-Zeiger oder leerer String: Ergebnis von strerror() wird ausgegeben In Bibliotheken üblicherweise nicht sehr brauchbar Späterer Einsatz nicht klar; Existenz von stderr nicht gesichert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 8 / 36
strerror et al. strerror bildet Fehlercode (errno) auf Text ab Aktuelle Locale wird verwendet Nutzt globalen Systempuffer String sollte nicht direkt modifiziert werden; kann Konstante sein String in Speicherblock der Anwendung kopieren Wird nie von Systemfunktionen selbst aufgerufen strerror_r sehr ähnlich zu strerror Nutzt von Anwendung bereitgestellter Puffer Ist thread-safe perror schreibt Meldung auf Standardfehlerausgabe (stderr) NULL-Zeiger oder leerer String: Ergebnis von strerror() wird ausgegeben In Bibliotheken üblicherweise nicht sehr brauchbar Späterer Einsatz nicht klar; Existenz von stderr nicht gesichert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 8 / 36
Tipps Vorsicht bei geschachtelten Funktionen strcpy(malloc(strlen(my_str)+1, my_str)); malloc kann natürlich fehlschlagen strcpy würde auf NULL-Zeiger arbeiten Einzelne Schritte separieren size_t str_len = strlen(my_str); char *ptr = (char *)malloc(str_len); if (!ptr) /* Fehlerbehandlung */ strcpy(ptr, my_str); Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 9 / 36
Beispiel DB2 Code sqlzrc myfunction(...) { sqlzrc rc = SQL_OK; char *buffer = NULL;... buffer = (char *)malloc(length); if (buffer!= NULL) { rc = SQLZ_OUT_OF_MEMORY; goto cleanup; } Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 10 / 36
Beispiel DB2 Code (cont.) rc = sqluimpr(...); if (rc!= SQL_OK) { goto cleanup; }... } cleanup: if (buffer!= NULL) { free(buffer); } Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 11 / 36
Fehlerbehandlung in Anwendungen Im Fehlerfall muss jede Funktion einen wohldefinierten Zustand hinterlassen, z. B. Allokierten Speicher wieder freigeben Geänderte Signal-Handler zurücksetzen Fehlermeldungen und -informationen setzen Nie, nie und nie exit und abort verwenden!! Funktion kann (irgendwann) in Bibliothek landen Bibliotheken werden von verschiedenen Programmen verwendet exit/abort würde Programm beenden, dass Bibliothek nur verwendet Fehler einfach zum Aufrufen durchreichen Erfordert entsprechendes Design von Grund auf Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 12 / 36
Fehlerbehandlung in Anwendungen Im Fehlerfall muss jede Funktion einen wohldefinierten Zustand hinterlassen, z. B. Allokierten Speicher wieder freigeben Geänderte Signal-Handler zurücksetzen Fehlermeldungen und -informationen setzen Nie, nie und nie exit und abort verwenden!! Funktion kann (irgendwann) in Bibliothek landen Bibliotheken werden von verschiedenen Programmen verwendet exit/abort würde Programm beenden, dass Bibliothek nur verwendet Fehler einfach zum Aufrufen durchreichen Erfordert entsprechendes Design von Grund auf Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 12 / 36
Numerische Fehler Keine Laufzeitüberprüfungen bei numerischen Operationen Überläufe und Unterläufe möglich; werden nicht automatisch erkannt Muss von Anwendung explizit abgefangen werden Integer-Zahlen (signed/unsigned) char, short, int, long, long long Grenzen (min/max) in <limits.h> definiert Numerische Genauigkeit von Fliesskommazahlen Test auf Gleichheit zweier Zahlen nicht exakt if (fabs(flt1 - flt2) <= ɛ) {... } Vordefinierte Macros (kleinste Zahl > 1, die darstellbar ist): FLT_EPSILON und DBL_EPSILON Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 13 / 36
Numerische Fehler Keine Laufzeitüberprüfungen bei numerischen Operationen Überläufe und Unterläufe möglich; werden nicht automatisch erkannt Muss von Anwendung explizit abgefangen werden Integer-Zahlen (signed/unsigned) char, short, int, long, long long Grenzen (min/max) in <limits.h> definiert Numerische Genauigkeit von Fliesskommazahlen Test auf Gleichheit zweier Zahlen nicht exakt if (fabs(flt1 - flt2) <= ɛ) {... } Vordefinierte Macros (kleinste Zahl > 1, die darstellbar ist): FLT_EPSILON und DBL_EPSILON Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 13 / 36
Numerische Fehler Keine Laufzeitüberprüfungen bei numerischen Operationen Überläufe und Unterläufe möglich; werden nicht automatisch erkannt Muss von Anwendung explizit abgefangen werden Integer-Zahlen (signed/unsigned) char, short, int, long, long long Grenzen (min/max) in <limits.h> definiert Numerische Genauigkeit von Fliesskommazahlen Test auf Gleichheit zweier Zahlen nicht exakt if (fabs(flt1 - flt2) <= ɛ) {... } Vordefinierte Macros (kleinste Zahl > 1, die darstellbar ist): FLT_EPSILON und DBL_EPSILON Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 13 / 36
Outline 1 Fehlerbehandlung Grundsatz Mechanismen zur Fehlererkennung Tipps & Hinweise 2 Internationalisierung Internationalisierung vs. Lokalisierung X/Open Message Catalogs GNU gettext 3 Programmende 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 14 / 36
Grundlagen Alle Texte eines Programms müssen an jeweilige Sprache angepasst werden. Internationalization (I18N) Programm vorbereiten auf dynamische Meldungen/Texte Localization (L10N) Übersetzen der Meldungen in die jeweilige Sprache Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 15 / 36
Grundlagen Alle Texte eines Programms müssen an jeweilige Sprache angepasst werden. Internationalization (I18N) Programm vorbereiten auf dynamische Meldungen/Texte Localization (L10N) Übersetzen der Meldungen in die jeweilige Sprache Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 15 / 36
Grundlagen Alle Texte eines Programms müssen an jeweilige Sprache angepasst werden. Internationalization (I18N) Programm vorbereiten auf dynamische Meldungen/Texte Localization (L10N) Übersetzen der Meldungen in die jeweilige Sprache Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 15 / 36
Internationalisierung Unterschiedliche Länge von Texten Unterschiedliche Darstellungsformate für Datum, Uhrzeit, Zahlen, Währungen,... 11/01/06 vs. 01.11.06 vs. 2006-11-01 1:20 PM vs. 13:20 123,456.78 vs. 123456,78-890 vs. (890) oft bei negativen Geldbeträgen 120 EUR vs. $120 Richtung des Textes kann variieren: 1 Von links nach rechts (z. B. English, Deutsch,... ) 2 Von rechts nach links (z. B. Arabische Sprachen) 3 Von oben nach unten (z. B. Japanisch) Statische Annahmen nicht haltbar. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 16 / 36
Internationalisierung Unterschiedliche Länge von Texten Unterschiedliche Darstellungsformate für Datum, Uhrzeit, Zahlen, Währungen,... 11/01/06 vs. 01.11.06 vs. 2006-11-01 1:20 PM vs. 13:20 123,456.78 vs. 123456,78-890 vs. (890) oft bei negativen Geldbeträgen 120 EUR vs. $120 Richtung des Textes kann variieren: 1 Von links nach rechts (z. B. English, Deutsch,... ) 2 Von rechts nach links (z. B. Arabische Sprachen) 3 Von oben nach unten (z. B. Japanisch) Statische Annahmen nicht haltbar. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 16 / 36
Internationalisierung Unterschiedliche Länge von Texten Unterschiedliche Darstellungsformate für Datum, Uhrzeit, Zahlen, Währungen,... 11/01/06 vs. 01.11.06 vs. 2006-11-01 1:20 PM vs. 13:20 123,456.78 vs. 123456,78-890 vs. (890) oft bei negativen Geldbeträgen 120 EUR vs. $120 Richtung des Textes kann variieren: 1 Von links nach rechts (z. B. English, Deutsch,... ) 2 Von rechts nach links (z. B. Arabische Sprachen) 3 Von oben nach unten (z. B. Japanisch) Statische Annahmen nicht haltbar. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 16 / 36
Internationalisierung Unterschiedliche Länge von Texten Unterschiedliche Darstellungsformate für Datum, Uhrzeit, Zahlen, Währungen,... 11/01/06 vs. 01.11.06 vs. 2006-11-01 1:20 PM vs. 13:20 123,456.78 vs. 123456,78-890 vs. (890) oft bei negativen Geldbeträgen 120 EUR vs. $120 Richtung des Textes kann variieren: 1 Von links nach rechts (z. B. English, Deutsch,... ) 2 Von rechts nach links (z. B. Arabische Sprachen) 3 Von oben nach unten (z. B. Japanisch) Statische Annahmen nicht haltbar. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 16 / 36
Lokalisierung LOCALE beeinflusst verschiedene Darstellungsarten Regionaleinstellung Meldungen müssen speziell übersetzt werden Reihenfolge von Tokens in Meldungen kann sich ändern Anderer Satzbau Message Catalogs sammeln Meldungen in einer spezifischen Sprache bzw. Dialekt Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 17 / 36
Message Catalogs a la X/Open Textdatei mit Meldungen Jede Meldung erhält eindeutigen numerischen Identifier set + msg-id Programme arbeiten nur mit Identifier Formatierung der Meldungen kann mit printf-funktionen erfolgen Arbeit mit Katalogen ähnlich zu read-only Dateien: 1 open 2 get message 3 close Header-Datei <nl_types.h> Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 18 / 36
catopen nl_catd catopen(const char *cat_name, int flag) Öffnet angegebenen Katalog Gibt Katalogdeskriptor zurück Lokation des Katalogs im Dateisystem: Absoluter oder relativer Pfad, oder Umgebungsvariable NLSPATH Pfade sollten nie verwendet werden da nicht portabel. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 19 / 36
catgets char *catgets(nl_catd cat, int set, int msg, const char *str) Ermittelt identifizierte Meldung Falls Meldung nicht existiert, dann wird str zurückgegeben Muss zur Fehlerbehandlung verwendet werden char *msg = catgets(..., default); if (msg == default) { /* Fehler: fehlende Meldung */ } Meldung sollte für Modifikationen in eigenen Puffer kopiert werden Formatierung: Some error encountered at position %1d. sprintf(formattedmsg, msg, tokens,...) Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 20 / 36
catclose int catclose(nl_catd cat) Schliesst Katalog Gibt Resourcen frei Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 21 / 36
gettext char *gettext(char *) Ähnlich zu X/Open Meldungen in Katalogen separat von Programmcode gesammelt Auswahl des entsprechenden Katalogs Funktion zum ermittelt der korrekten, übersetzten Meldung Probleme bei X/Open Pflege der eindeutigen Nummern der Meldungen gettext verwendet Meldung als Identifier Identifier ist gleichzeitig Default-Meldung Werkzeuge: xgettext erkennt alle (markierten) Meldungen eines Programms; erzeugt Template für Übersetzung msgmerge aktualisiert Katalog mit neuen Meldungen msgfmt erzeugt Binärformat des Katalogs, welchen gettext zur Laufzeit konsultiert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 22 / 36
gettext char *gettext(char *) Ähnlich zu X/Open Meldungen in Katalogen separat von Programmcode gesammelt Auswahl des entsprechenden Katalogs Funktion zum ermittelt der korrekten, übersetzten Meldung Probleme bei X/Open Pflege der eindeutigen Nummern der Meldungen gettext verwendet Meldung als Identifier Identifier ist gleichzeitig Default-Meldung Werkzeuge: xgettext erkennt alle (markierten) Meldungen eines Programms; erzeugt Template für Übersetzung msgmerge aktualisiert Katalog mit neuen Meldungen msgfmt erzeugt Binärformat des Katalogs, welchen gettext zur Laufzeit konsultiert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 22 / 36
gettext char *gettext(char *) Ähnlich zu X/Open Meldungen in Katalogen separat von Programmcode gesammelt Auswahl des entsprechenden Katalogs Funktion zum ermittelt der korrekten, übersetzten Meldung Probleme bei X/Open Pflege der eindeutigen Nummern der Meldungen gettext verwendet Meldung als Identifier Identifier ist gleichzeitig Default-Meldung Werkzeuge: xgettext erkennt alle (markierten) Meldungen eines Programms; erzeugt Template für Übersetzung msgmerge aktualisiert Katalog mit neuen Meldungen msgfmt erzeugt Binärformat des Katalogs, welchen gettext zur Laufzeit konsultiert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 22 / 36
gettext char *gettext(char *) Ähnlich zu X/Open Meldungen in Katalogen separat von Programmcode gesammelt Auswahl des entsprechenden Katalogs Funktion zum ermittelt der korrekten, übersetzten Meldung Probleme bei X/Open Pflege der eindeutigen Nummern der Meldungen gettext verwendet Meldung als Identifier Identifier ist gleichzeitig Default-Meldung Werkzeuge: xgettext erkennt alle (markierten) Meldungen eines Programms; erzeugt Template für Übersetzung msgmerge aktualisiert Katalog mit neuen Meldungen msgfmt erzeugt Binärformat des Katalogs, welchen gettext zur Laufzeit konsultiert Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 22 / 36
Outline 1 Fehlerbehandlung Grundsatz Mechanismen zur Fehlererkennung Tipps & Hinweise 2 Internationalisierung Internationalisierung vs. Lokalisierung X/Open Message Catalogs GNU gettext 3 Programmende 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 23 / 36
Programmende Programm endet wenn Funktion main wird verlassen Funktion exit wird aufgerufen Funktion abort wird aufgerufen Programm muss Exit-Status zurückgeben main muss mit return-operation beendet werden exit erhält expliziten Status als Parameter abort sendet SIGABRT Signal Betriebssystem räumt nach Programm auf File-Deskriptoren Speicher... Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 24 / 36
Programmende Programm endet wenn Funktion main wird verlassen Funktion exit wird aufgerufen Funktion abort wird aufgerufen Programm muss Exit-Status zurückgeben main muss mit return-operation beendet werden exit erhält expliziten Status als Parameter abort sendet SIGABRT Signal Betriebssystem räumt nach Programm auf File-Deskriptoren Speicher... Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 24 / 36
Programmende Programm endet wenn Funktion main wird verlassen Funktion exit wird aufgerufen Funktion abort wird aufgerufen Programm muss Exit-Status zurückgeben main muss mit return-operation beendet werden exit erhält expliziten Status als Parameter abort sendet SIGABRT Signal Betriebssystem räumt nach Programm auf File-Deskriptoren Speicher... Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 24 / 36
Verlassen von main Erfolgreiches Ende mit 0 gekennzeichnet; sonst Fehler Header-Datei <stdlib.h> definiert (POSIX): EXIT_SUCCESS EXIT_FAILURE Alles andere systemspezifisch; potentiell nicht portabel Rückgabewert kann abgefragt werden In Shell/Perl z. B. Variable $? Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 25 / 36
exit void exit(int status) Ende des Programms aus beliebiger (geschachtelter) Routine Interne Funktion _exit() wird aufgerufen Exit-Handler werden abgearbeitet Status wird als Exit-Status des Programms zurückgegeben exit sollte nie verwendet werden. Vergleichbar zu Javas System.exit() Aber kein Security Manager o.ä. vorhanden Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 26 / 36
exit void exit(int status) Ende des Programms aus beliebiger (geschachtelter) Routine Interne Funktion _exit() wird aufgerufen Exit-Handler werden abgearbeitet Status wird als Exit-Status des Programms zurückgegeben exit sollte nie verwendet werden. Vergleichbar zu Javas System.exit() Aber kein Security Manager o.ä. vorhanden Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 26 / 36
exit void exit(int status) Ende des Programms aus beliebiger (geschachtelter) Routine Interne Funktion _exit() wird aufgerufen Exit-Handler werden abgearbeitet Status wird als Exit-Status des Programms zurückgegeben exit sollte nie verwendet werden. Vergleichbar zu Javas System.exit() Aber kein Security Manager o.ä. vorhanden Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 26 / 36
Exit Handler Registrierte Funktionen, die beim Ende des Programms abgearbeitet werden Funktionen atexit() und on_exit() int atexit(void (*function)(void)) Registriert lediglich die angegebene Funktion function int on_exit(void (*function)(int, void *), void *arg) Registriert die angegebene Funktion function und den Zeiger auf einen Speicherbereich arg Speicherbereich wird Funktion als Parameter beim Aufruf übergeben arg muss beim exit auf gültigen Bereich zeigen Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 27 / 36
Funktionszeiger Deklaration: return-type (*name)(parameter-type,...) Verwendung: name(parameter-value,...) Oft in typedef verborgen typedef int (*function_type)(int, char); int my_fct(int i, char c) {... } int main() { function_type f = my_fct; res = f(1, a ); } Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 28 / 36
abort void abort(void) Abnormales Beenden des Programms Programm erhält abort Signal (SIGABRT) Signal-Handler für SIGABRT kann verwendet werden Kein Aufräumen Keine Exit-Handler Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 29 / 36
Outline 1 Fehlerbehandlung Grundsatz Mechanismen zur Fehlererkennung Tipps & Hinweise 2 Internationalisierung Internationalisierung vs. Lokalisierung X/Open Message Catalogs GNU gettext 3 Programmende 4 Aufgaben Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 30 / 36
Aufgabe 1 Schreiben Sie ein Programm, welches versucht eine Datei zu öffnen, deren Name als Kommandozeilenparameter an das Programm übergeben wurde. a) Wenn die Datei geöffnet werden kann, so sind alle Zahlen in der Datei zu ermitteln. Die Anzahl dieser Zahlen ist zu ermitteln und auf die Standardausgabe auszugeben. b) Wenn die Datei nicht geöffnet werden kann, so ist eine detailierte Fehlermeldung auszugeben, warum die Datei nicht geöffnet werden konnte. Verwenden Sie einen Exit Handler, um die Datei beim Beenden des Programms korrekt zu schliessen. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 31 / 36
Aufgabe 2 Legen Sie zwei Message Catalogs an, die jeweils 1 Set mit 10 verschiedenen Meldungen (in Deutsch und Englisch) enthalten. Die Meldungen sollen es ermöglichen, den Ablauf eines kurzen, selbst geschriebenen Programms nachzuverfolgen, also eine Art Trace produzieren für: a) das Betreten einer Funktion, b) das Verlassen einer Funktion, und c) eine funktionsspezifische Meldung Zeigen Sie dabei, dass abhängig von den Einstellungen in der Umgebung einmal die Englischen und einmal die Deutschen Meldungen ausgegeben werden. Verwenden Sie dabei die X/Open Schnittstelle für Message Catalogs. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 32 / 36
Aufgabe 3 Lösen Sie die gleiche Aufgabenstellung wie zuvor in Aufgabe 2, verwenden Sie jedoch diesmal das GNU gettext Interface. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 33 / 36
Aufgabe 4 Schreiben Sie ein Programm, welches ein Array mit 5 Funktionszeigern dynamisch (per malloc) anlegt. Jedem der Array-Elemente ist eine Funktion zuzuordnen. Rufen Sie anschliessend die Funktionen in einer Schleife auf und geben Sie deren Ergebnis im Schleifenrumpf (nicht in der Funktion selbst) auf die Standardausgabe aus. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 34 / 36
Aufgabe 5 Implementieren Sie ein Programm, welches eine Struktur definiert, die entweder für eine Datei (FILE *) oder einen String (char *) die folgenden Operationen zur Verfügung stellt: a) Ermitteln des nächsten zu lesenden Zeichens (Bytes) b) Ermitteln der Länge der noch nicht gelesenen Daten c) Schliessen der Datei bzw. Freigeben des Strings Zwei separate Funktionen zur Initialisieren der Struktur in Abhängigkeit ven Datei bzw. String sind umzusetzen. Diese beiden Funktionen setzen die Funktionszeiger in der Struktur auf die spezifischen Routinen. Die Struktur ist nach Bedarf mit eigenen Erweiterungen zu versehen. Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 35 / 36
Aufgabe 5 (cont.) Die Struktur implementiert einen Mechanismus, der vergleichbar zu der Vererbungshierarchie in folgendem Bild ist (ohne jedoch Vererbung zu nutzen). Die gezeigten Attribute nehmen Funktionszeiger auf, die als Callback-Funktionen Verwendung finden, d. h. abhängig vom jeweiligen Einsatz/Initialisierung wird die entsprechende spezifische Funktion aufgerufen. my_stream get_next_byte get_remaining_length close FILE_stream String_stream Knut Stolze (DBIS) C/C++ Programmierung 2006 11 01 36 / 36