Forum: PC-Programmierung TRY CATCH in C


von Der Programmierwolf (Gast)


Lesenswert?

gibt es bei C kein TRY/CATCH wie bei JAVA?

von Peter II (Gast)


Lesenswert?

Der Programmierwolf schrieb:
> gibt es bei C kein TRY/CATCH wie bei JAVA?

nein, sonst währe es ja c++

von Kaj (Gast)


Lesenswert?

Wenn ich das recht weiß, gibt es in C auch keine Exceptions. Damit 
braucht man auch kein try/catch. Man braucht nichts fangen, was es nicht 
gibt.

von Dennis S. (eltio)


Lesenswert?

Aber es gibt assert. Klar, ist nicht das Gleiche aber vielleicht hilft 
es dir weiter!

Gruß Dennis

von Daniel A. (daniel-a)


Lesenswert?

Kaj schrieb:
> Wenn ich das recht weiß, gibt es in C auch keine Exceptions. Damit
> braucht man auch kein try/catch. Man braucht nichts fangen, was es nicht
> gibt.

Es gibt zwar kein try catch, exeptions aber, je nach Platform, schon. 
0.0f/1.0f kann zu einer floating point exeption füren. Wenn du ohne 
nicht leben kannst, dann mach in C++ ne lib, in welcher du eine
1
void throwFunc(void*)
 schreibst, und ein
1
void catchFunc(void(*)(void*,void*),void*)
, welche du in deine c Application einbindest. (Ist aber eine schlechte 
Idee)

von Klaus W. (mfgkw)


Lesenswert?

Daniel A. schrieb:
> Es gibt zwar kein try catch, exeptions aber, je nach Platform, schon.
> 0.0f/1.0f kann zu einer floating point exeption füren.

Auch wenn es exception heißt, ist es keine, die man mit irgendwelchen 
Sprachmitteln fangen kann.
Es wird nur ein Zustand signalisiert, den man erkennen und darauf 
reagieren kann.
In dem Zusammenhang Stack aufräumen, Destruktoren aufräumen oder andere 
Speilereien: Fehlanzeige.

von Oliver (Gast)


Lesenswert?

C kennt setjmp/longjmp, mehr nicht.

Oliver

von Klaus W. (mfgkw)


Lesenswert?

... und damit kann man keine Exceptions wirklich nachbauen, weil die 
Freigabe aller Resourcen auf dem Stack bei einem longjmp() fehlt.

: Bearbeitet durch User
von ah8 (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> ... und damit kann man keine Exceptions wirklich nachbauen, weil die
> Freigabe aller Resourcen auf dem Stack bei einem longjmp() fehlt.

Könnte man schon, man bräuchte halt für jeden catch-Block eine setjump, 
müsste die Sprungziele in einer verketteten Liste auf dem Stack 
verknüpfen und der Reihe nach anspringen. Ressourcenfreigabe muss man in 
C ohnehin manuell machen, dass ließe sich in einen solchen Mechanismus 
integrieren. Ob sich dieser Aufwand allerdings lohnt? Immerhin hätte 
dieser Mechanismus den Vorteil, auch aus Signalhändlern heraus 
aufgerufen werden zu können, etwas was Exceptions meines Wissens nach 
nicht bieten.

von B. S. (bestucki)


Lesenswert?


von ah8 (Gast)


Lesenswert?

be stucki schrieb:
> Hier gibt es was zu lesen und Code:
> http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html

Ein schöner Beitrag, er zeigt das Prinzip, ist aber leider nicht 
wirklich zu Ende gedacht. Hauptproblem ist, dass der jmp_buf lokal 
angelegt wird, er ist also nur innerhalb der jeweiligen Funktion 
sichtbar und kann nur von dort angesprungen werden. Dazu reicht im 
Prinzip aber auch ein goto. Zweck des longjump ist es ja gerade, auch 
über Funktionsgrenzen hinweg aus einer (eventuell tief geschachtelten) 
Aufrufhierarchie zurück zu springen. Dazu müsste jmp_buf aber immer in 
irgendeiner Form global (erreichbar) sein.

von Dr. Sommer (Gast)


Lesenswert?

ah8 schrieb:
> Ob sich dieser Aufwand allerdings lohnt?
Man könnte auch einfach C++ verwenden...
> Immerhin hätte
> dieser Mechanismus den Vorteil, auch aus Signalhändlern heraus
> aufgerufen werden zu können, etwas was Exceptions meines Wissens nach
> nicht bieten.
Ob das ein Vorteil ist, wenn an irgendeiner Stelle im Code plötzlich 
eine "Exception" fliegen kann? signale sind eh eine antike Technik für 
typische Frickel-C-Programme. Bei sauberer Programmierung verwendet man 
Warten ala select() o.ä. und fängt alle möglichen Ursachen von Signalen 
explizit auf. Wenn man unbedint ein signal braucht um auf SIGCHLD oder 
so zu warten sollte man vielleicht lieber das Signal auf SIGIGN stellen, 
den Rückgabewert von select() o.ä. auswerten (errno = EINTR) und mit 
waitpid o.ä. den Status explizit abfragen. Dann Exceptions zu werfen 
zerstört nicht den kompletten Programmfluss...

von ah8 (Gast)


Lesenswert?

Dr. Sommer schrieb:

> Ob das ein Vorteil ist, wenn an irgendeiner Stelle im Code plötzlich
> eine "Exception" fliegen kann? signale sind eh eine antike Technik für
> typische Frickel-C-Programme.

Signale haben nichts mit C zu tun. Signale sind ein Kommunikationsmittel 
des Unix Kernels und ja, Signale können an jeder beliebigen Stelle im 
Code eintreffen. Das ist sicher nicht immer schön, aber es ist nun mal 
so, ohne dass ich als Programmierer auch nur die Spur einer Chance habe, 
das zu verhindern. Mir bleibt nur, mich dieser Realität zu stellen, zum 
Beispiel, da sind wir einer Meinung, durch Signalhandler. Nun kann ich, 
je nach Signal, in einem Handler durchaus versuchen, etwas sinnvolles zu 
tun, meistens aber ist die einzig sinnvolle Alternative, das Programm zu 
beenden. Dabei kann es noch etwas aufzuräumen geben. In C++ ist das mit 
Exception grundsätzlich wunderbar zu machen, nur leider ist das Auslösen 
einer Exception in einem Signalhandler ein nicht definiertes Verhalten, 
mit anderen Worten, für diesen Zweck sind Exceptions nutzlos und nein, 
C++ (nur deswegen) zu nehmen ist in diesem Fall keine Lösung. Das 
Verhalten von longjump dagegen ist in einer solchen Situation sehr wohl 
definiert, folglich kann ich es für ein Ressourcenmanagement in solchen 
Fällen verwenden und ja, das ist ein Vorteil gegenüber Exceptions. Ob 
das nun die beste Lösung ist und ob die Vorteile die Nachteile 
aufwiegen, das steht natürlich auf einem ganz anderen Blatt.

von Dr. Sommer (Gast)


Lesenswert?

ah8 schrieb:
> Signale haben nichts mit C zu tun. Signale sind ein Kommunikationsmittel
> des Unix Kernels
Nur dass C "die" Sprache von Unix ist, und ein Gutteil des 
UNIX(POSIX)-API's direkt auf C gemünzt ist, wie zB execl - und eben 
signale. Wie viele andere Sprachen verwenden denn UNIX-Signale direkt, 
genau so wie in C?
> und ja, Signale können an jeder beliebigen Stelle im
> Code eintreffen. Das ist sicher nicht immer schön, aber es ist nun mal
> so, ohne dass ich als Programmierer auch nur die Spur einer Chance habe,
> das zu verhindern.
SIGIGN wäre eine Möglichkeit. Oder einfach keine Exceptions im 
Signalhandler werfen, dann hast du das Problem nicht.
> Mir bleibt nur, mich dieser Realität zu stellen, zum
> Beispiel, da sind wir einer Meinung, durch Signalhandler. Nun kann ich,
> je nach Signal, in einem Handler durchaus versuchen, etwas sinnvolles zu
> tun, meistens aber ist die einzig sinnvolle Alternative, das Programm zu
> beenden.
Bei SIGCHLD, SIGWINCH, SIGALRM macht man typischerweise was ganz anderes 
als das Programm zu beenden...
> Dabei kann es noch etwas aufzuräumen geben.
Bloß, wenn du als Reaktion auf einen Signalhandler dein Programm beenden 
willst, dann handelt es sich vermutlich  um SIGSEGV o.ä., d.h. dein 
Programm ist schon in einem kaputten Zustand, und dann solltest du eh 
nicht mehr viel Magic (longjmp/Exceptions) machen sondern möglichst 
"sicher" beenden... Wenn du aber noch in einem "normalen" Zustand bist 
und normal Beenden willst (zB SIGINT), kannst du im Signalhandler auch 
einfach nur ein Flag setzen und im nächsten Lauf der mainloop (select) 
sauber per C++ Exception beenden.
> und nein,
> C++ (nur deswegen) zu nehmen ist in diesem Fall keine Lösung.
Wenn du ein Resourcenmanagement betreiben möchstest ist es sehr sinnvoll 
C++ zu verwenden, welches aufgrund von Smartpointern, Exceptions, 
Destruktoren ein viel einfacheres&sichereres Verwalten&Aufräumen als C 
ermöglicht.

von ah8 (Gast)


Lesenswert?

Dr. Sommer schrieb:
> ah8 schrieb:
>> Signale haben nichts mit C zu tun. Signale sind ein Kommunikationsmittel
>> des Unix Kernels
> Nur dass C "die" Sprache von Unix ist, und ein Gutteil des
> UNIX(POSIX)-API's direkt auf C gemünzt ist, wie zB execl - und eben
> signale. Wie viele andere Sprachen verwenden denn UNIX-Signale direkt,
> genau so wie in C?

Jedem (!) Programm, was auf einem Unix System abgearbeitet wird, kann zu 
jeder (!) Zeit ein Signal gesendet werden, sei es vom Nutzer, dem Kernel 
oder einem anderen Prozess. Dabei spielt es absolut keine Rolle, in 
welcher Sprache das Programm oder das Betriebssystem geschrieben sind. 
Es gibt Signale, die standardmäßig ignoriert werden und solche, die zum 
Programmabbruch führen, mit oder ohne core-Dump. Dieses Verhalten mag 
angemessen sein oder nicht. Es mag Sprachen geben, die keine 
Sprachmittel zur Verfügung stellen, um auf Signale zu angemessen zu 
reagieren und es mag Anwendungen geben, bei denen das gar nicht nötig 
ist. Ich rede hier aber von den Fällen, wo es nötig ist und da muss ich 
im Zweifel eine Sprache wählen, die das kann.

>> und ja, Signale können an jeder beliebigen Stelle im
>> Code eintreffen. Das ist sicher nicht immer schön, aber es ist nun mal
>> so, ohne dass ich als Programmierer auch nur die Spur einer Chance habe,
>> das zu verhindern.
> SIGIGN wäre eine Möglichkeit.

Ist es nicht, zumindest keine allgemeingültige. Es sei denn, ich bin als 
Programmierer bereit, undefiniertes Verhalten zu akzeptieren. Das 
Verhalten beim Ignorieren von bestimmten Signalen (SIGFPE, SIGILL, oder 
SIGSEGV z.B.) ist laut POSIX Standard nämlich nicht definiert. Ich rede 
hier unter anderem genau von den Fällen.

> Oder einfach keine Exceptions im
> Signalhandler werfen, dann hast du das Problem nicht.

Ich würde nie in einem Signalhandler eine Exception werfen, dass führt 
nämlich (je nach System, Compiler und Signal) auch zu undefiniertem 
Verhalten.

>> Mir bleibt nur, mich dieser Realität zu stellen, zum
>> Beispiel, da sind wir einer Meinung, durch Signalhandler. Nun kann ich,
>> je nach Signal, in einem Handler durchaus versuchen, etwas sinnvolles zu
>> tun, meistens aber ist die einzig sinnvolle Alternative, das Programm zu
>> beenden.
> Bei SIGCHLD, SIGWINCH, SIGALRM macht man typischerweise was ganz anderes
> als das Programm zu beenden...

OK, ich ändere meine Formulierung von 'meisten' in 'oft' oder 
meinetwegen auch 'manchmal'. Das ändert aber nichts an der 
grundsätzlichen Aussage, dass es Signale und Situationen gibt, in denen 
das Beenden des Programms die einzige sinnvolle Alternative bleibt und 
ein allgemeingültiges Ressourcenmanagement in der Lage sein muss, mit 
diesen Situationen umzugehen.

>> Dabei kann es noch etwas aufzuräumen geben.
> Bloß, wenn du als Reaktion auf einen Signalhandler dein Programm beenden
> willst, dann handelt es sich vermutlich  um SIGSEGV o.ä., d.h. dein
> Programm ist schon in einem kaputten Zustand, und dann solltest du eh
> nicht mehr viel Magic (longjmp/Exceptions) machen sondern möglichst
> "sicher" beenden...

Ein robustes Programm würde auch in solchen Situationen zumindest 
versuchen, essentielle Dinge noch aufzuräumen. Abgesehen davon steht 
nirgends in Stein gemeißelt, dass das so sein muss. Im Gegenteil, ein 
gutes Design würde immer versuchen, die Effekte selbst solcher Fehler 
lokal zu begrenzen, zumindest so lange, bis alles Wesentlich aufgeräumt 
ist.

> Wenn du aber noch in einem "normalen" Zustand bist
> und normal Beenden willst (zB SIGINT), kannst du im Signalhandler auch
> einfach nur ein Flag setzen und im nächsten Lauf der mainloop (select)
> sauber per C++ Exception beenden.

Das Senden eines Signals sollte eigentlich (fast) nie der 'normale' Weg 
sein, ein Programm zu beenden. Im Gegenteil, wenn der Nutzer ein SIGINT 
sendet (INT steht für Interrupt = Unterbrechung), dann wird er wohl 
gerade nicht warten wollen bis das Programm das nächste Mal in seiner 
Mainloop vorbei kommt, sondern dass es sofort (!) reagiert, aus welchen 
Gründen auch immer. Übrigens, wenn ich dann wieder in der Mainloop 
ankomme, dann brauche ich keine Exception mehr, dann kann ich das 
Programm ganz normal beenden. Exception heißt Ausnahme und ist 
normalerweise – so jedenfalls meine Definition – für Situationen 
reserviert, die außerhalb des meiner Implementierung zu Grunde liegenden 
Modells liegen. Das Beenden eines Programms gehört ganz sicher nicht 
dazu.

>> und nein,
>> C++ (nur deswegen) zu nehmen ist in diesem Fall keine Lösung.
> Wenn du ein Resourcenmanagement betreiben möchstest ist es sehr sinnvoll
> C++ zu verwenden, welches aufgrund von Smartpointern, Exceptions,
> Destruktoren ein viel einfacheres&sichereres Verwalten&Aufräumen als C
> ermöglicht.

Alles richtig, ich möchte auch nichts gegen C++ und sein 
Ressourcenmanagement gesagt haben. Ich programmiere oft und gerne in 
C++. Es hat aber sein Grenzen: Das Auslösen einer Exception aus einem 
Signalhandler heraus ist nicht portabel definiert und somit ein No Go. 
Wenn ich aber genau dieses Problem habe, aus einem Signalhandler heraus 
Ressourcenmanagement betreiben zu müssen, sind C++ Exceptions schlicht 
nutzlos. Punkt! Das, und nichts anderes habe ich gesagt. Wenn es keine 
anderen Gründe gibt, die in einem konkreten Fall für C++ sprechen, ist 
es folglich auch sinnlos, es zu verwenden.

von Berlin-Fanclub (Gast)


Lesenswert?

> be stucki schrieb:
> Hier gibt es was zu lesen und Code:
> http://www.di.unipi.it/~nids/docs/longjump_try_tro...

> Ein schöner Beitrag, er zeigt das Prinzip, ist aber leider nicht
> wirklich zu Ende gedacht. Hauptproblem ist, dass der jmp_buf lokal
> angelegt wird, er ist also nur innerhalb der jeweiligen Funktion
> sichtbar und kann nur von dort angesprungen werden.
es gibt noch 1000 andere Beispiele wie das in C geht:
http://www.adomas.org/excc/

> Man könnte auch einfach C++ verwenden...
das wäre sinnvoller, prinzipiell muß es auch in C funktionieren, wird 
dann halt komplizierter.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.