Hallo,
ich hätte da eine Frage bezüglich der Fehlerbehandlung in C. Ich kenne
die Konzepte der Fehlerbehandlung ( return, longjmp, lokaler Fehlerindex
). Was mir aber bei diesen fehlt ist, dass ich nicht weiss wer den
Fehler verursacht hat (also welche Funktion). Bsp:
Ich hoffe es funktioniert auch, kann es jetzt nicht testen (grad kein
Compiler zur Verfügung). Das Problem dieser Methode ist (oder eigentlich
alle die ich kenne), dass ich keine Informationen, wer der Verursacher
ist, bekomme. Sie kann mir zwar sagen, dass in doSomething() der Fehler
aufgetreten ist und was für einer, allerdings erfahre ich nicht, dass es
in Wirklichkeit main() ist. Also wenn ein falscher übergabe Wert
übergeben wurde. Ich hoffe es ist verständlich. Bei C# sieht man gleich
den ganzen Aufrufbaum der Funktionen (bzw. Methoden).
Kurz und knapp wie macht ihr das? Gut bei kleinen Programmen ist die
einfache schon in Ordnung, aber bei größeren Projekten, wo eine Funktion
1000 aufgerufen wird.
Vielen Dank für eure Antworten :).
er möchte einen CallStack!
Man müsste es selber Programmieren, in jeder funktion ruft man ein Makro
auf was den funktionsnamen und eventeull noch die Parameter auf den
"Stack" legt und diese am ende auch wieder entfernt. Und Genau das ist
schon ein Problem denn man muss immer dafür sorgen das es wieder
entfernt wird wenn die funktion verlassen wird.
C++ und den Destruktoren geht das etwas eleganter.
Aber soweit ich weiss gibt assert Datei und Linie von dort aus wo auch
assert aufgerufen wurde, also in doSomething().
Naja perror() und strerror() bringt mir nicht so viel, wenn ich den
Fehler in einem Fenster anzeige.
Genau das ist es was PeterII angesprochen hat. Allerdings ist es
ziemlich aufwendig, man müsste in jeder Funktion (wie main()) den
Funktionsnamen etc. setzen. Geht das nicht eleganter oder muss ich mich
damit zufrieden geben? Wie sucht man dann den Fehler bei einem großen
Programm, wo doSomething() 1000 aufgerufen wird? Raten und schauen ob
man Recht hat?
Wenn du jeder möglichen Fehlerstelle eine eindeutige Nummer zuornest,
die du zurückgibst, dann weisst du zumindest wo genau der Fehler
aufgetreten ist, auch wenn du keinen Call stack hast.
Wir haben da im allgemeinen ein eigenes Fehlermodul mit einer h Datei in
der alle Fehlernummern als Konstante definiert sind.
Das Problem ist bei allen Fehlerkonzepten, auch bei "try .. catch" etc.
man muss sich konsequent an sein System halten.
Christopher C. schrieb:> Allerdings ist es> ziemlich aufwendig, man müsste in jeder Funktion (wie main()) den> Funktionsnamen etc. setzen.
könnte man sogar per script mache, so aufwendig ist das nicht.
> Geht das nicht eleganter oder muss ich mich> damit zufrieden geben?
in C nicht.
> Wie sucht man dann den Fehler bei einem großen> Programm, wo doSomething() 1000 aufgerufen wird? Raten und schauen ob> man Recht hat?
mit dem Debugger - dort einfach den CallStack anzeigen. (in der hoffnung
das niemand der STack überschrieben hat)
Christopher C. schrieb:> Wie sucht man dann den Fehler bei einem großen> Programm, wo doSomething() 1000 aufgerufen wird? Raten und schauen ob> man Recht hat?
Problem nachstellen und debuggen
Oder einschaltbares Tracing mit unterschiedlichen Leveln. Dazu gibts
auch entsprechende Bibliotheken, Ich programmiere allerdings in den
letzten Jahren nur Java und wir benutzen log4j.
Zu den eindeutigen fehlernummern: Bei größeren Projekten übersichtlicher
wird es wenn man die Nummer aus einer Modulnr und der Fehlernummer
zusammensetzt. Also z.b. Modul 34 und Fehler 132 ergibt dann "034132".
Christopher C. schrieb:> Naja perror() und strerror() bringt mir nicht so viel, wenn ich den> Fehler in einem Fenster anzeige.
Bei perror kannst du ja noch zuätzlichen Erklärtext einfügen. Also
könntest du das noch mit
Danke so viele Rückmeldungen ;).
Der Trick mit der Modul-ID und der Callstack gefällt mir schon mal gut.
Es müsste eine Plattformunabhängige Lösung sein, weshalb der Callstack
rausfliegt, schade :(.
Weil das alles in der Rubrik PC-PRogrammierung steht, gehe ich davon
aus, daß es nicht um MC geht.
Dann frage ich mich aber, wieso man auf C besteht und nicht C++ nimmt.
Da kann man mit Ausnahmen viel schönere Sachen bauen.
Die beste Vorgehensweise zur Fehlerbehebung bzw. -Vermeidung im
Zusammenhang mit C: Schreibe den Programm mit einer RICHTIGEN
Programmiersprache und nicht mit diesem nutzlosen Frickler-Zeugs für
langhaarige Kellerkinder mit schweren sozialen Störungen.
(Rechner, auf denen C: zu finden ist, meide ich auch.)
Magst du deine Störungen nicht mal woanders ausleben, oder musst du
jetzt jeden Thread, wo du nichts Intelligentes zu sagen hast,
vollmüllen?
Ach egbert.
Halt dich einfach raus, wenn du keine Ahnung hast.
In Zukunft werd ich deine unqualifizierten Meldungen kommentarlos
löschen.
C ist eben nichts für Leute, die eine Tante brauchen, die mit ihnen Lulu
geht.
Udo Schmitt schrieb:> Karl Heinz Buchegger schrieb:>> In Zukunft werd ich deine unqualifizierten Meldungen kommentarlos>> löschen.> Warum erst in Zukunft?
Auch wieder wahr.
Aber erst mal soll er wissen, dass er sich vergebliche Tipparbeit macht.
> Ich hoffe es ist verständlich.
Ist es.
> Bei C# sieht man gleich den ganzen Aufrufbaum der Funktionen> (bzw. Methoden).
Siehst du im Debugger normalerweise auch. Wenn das Problem beim Kunden
auftritt, sieht die Sache aber anders aus.
Es gibt Runtime Systeme, die in solchen Fällen einen kompletten
Stackdump machen. Den kann der Kunde schicken und dann kann man den
analysieren. Manchmal hilft das sogar was. Denn in den meisten Fällen,
ist der interessante Teil nicht der, das das Programm abgeschmiert ist,
sondern der Weg wie es dazu gekommen ist. In einem realen Programm hat
eine Division durch 0 eine Vorgeschichte, die nicht selten in
irgendeiner vorhergehenden Benutzereingabe ihre Ursache hat (und das
muss nicht notwendigerweise die letzte gewesen sein). Dort steckt
irgendwo das eigentliche Problem.
Das ist das eine. Das andere ist: Ja C# kann das. Aber um welchen Preis?
Da wo C Programme noch einen kleinen schnuckeligen Speicherfootprint
haben, machen sich C# Programme im Speicher breit. C wurde eben in den
60-er Jahren nach dem Muster entworfen: You don't get for what you
didn't ask. Das Runtime System macht nur das, was absolut notwendig ist
um die Funktion zu erfüllen. Willst du mehr, dann musst du dir das
selber machen. Hat Nachteile, hat aber auch Vorteile: Du "erbst" nicht
riesige Bibliotheken mit einem unbedachten Funktionsaufruf.
> Wie sucht man dann den Fehler bei einem großen> Programm, wo doSomething() 1000 aufgerufen wird?
Letzten Endes gibts nur eines: testen, testen, testen.
In Idealfall ist nicht der Programmierer selbst der Tester, sondern du
hast eigene Leute dafür. Wenn die spitz kriegen "Operation X ist im
Zusammenhang Y nicht sinnvoll", dann testen die 100-erte Variationen von
X im Zusammenhang Y, alles was ihnen einfällt, um dein Programm zum
Absturz zu bringen (und genau das ist das, was Programmierer
normalerweise nicht tun) und sagen dir hinterher, wie sie den Absturz
geschafft haben.
assert wurde ja schon angesprochen. Ist ein hilfreiches Werkzeug in der
Debug-Phase, weil eine Funktion im Debugger laut 'Hilfe hier' schreit,
weil irgendwelche Dinge nicht so sind, wie sie eigentlich sein sollten.
Damit kriegt der Entwickler schon in der Entwicklungsphase eine Menge
Probleme in den Griff, die sonst erst beim Kunden auftreten würden und
dort ungleich mehr Schaden anrichten.
Karl Heinz Buchegger schrieb:> Letzten Endes gibts nur eines: testen, testen, testen.
nein hilft leider nicht.
Wenn man z.b. in eine Datei schreiben will und das write einen Fehler
liefert "fehler beim schreiben" dann hilft einem das überhaupt nicht
weiter. Die Write funktion selber kennt auch nur das fiele-handle damit
kann man auch nicht anfangen.
In so einen Fall braucht man für eine sinnvolle fehleranalyse einen
CallStack wo man sieht in welchen zusammenhang etwas in die Datei
geschrieben weden soll.
Und darin sehe ich wirklich ein Problem in C/C++ - die Fehlersuche ist
viel komplizierter als in C# oder Java.
Ich hatte es mal versucht mit Makros und C++ hinzubekommen, das man eine
CallStack bekommt - ja es geht aber es ist ein zusätzlicher Aufwand und
man muss sich zwingen es wirklich überall einzusetzen.
Peter II schrieb:> Und darin sehe ich wirklich ein Problem in C/C++ - die Fehlersuche ist> viel komplizierter als in C# oder Java.
Das stimmt, mit einem Stacktrace hat man schnell einen Anhaltspunkt wo
man mit der Suche anfangen muss. Und wenn dann die Exception noch ein
"Null-Pointer", eine "Array out of Bounds", eine "Data not numeric" oder
"Data truncation at Table, Row" liefert, dann hat man auch den Grund und
kann davon ausgehend zurückschauen.
Das hilft nicht immer aber sehr oft. Man spart sich nach meinen
Erfahrungen bai 30 -50% von Kundenproblemen das zuhause nachstellen,
bzw. kann das Problem gezielt und schnller nachstellen.
Aber was auf einem modernen PC kein Problem ist (große Runtime, viele
DLLs) ist auf einem µC oder auch einem ARM wieder was ganz anderes.
Genauso wie Geschwindigkeit wenn es mal wirklich darauf ankommt.