Wie ist euer Fehlersystem aufgebaut?



  • Anonsten: Lieber eine Software crashen lassen inkl. vernünftigen Crashdump, ale eine Fehlermeldung die weder dem Benutzer noch dem Entwickler hilft

    Dem kann ich leider überhaupt nicht zustimmen, denn es widerspricht auch der Definition von robuster Software.

    Eine sinnvolle Fehlermeldung, welche eine eindeutige Fehlernummer beinhaltet, sowie eine verbesserte Möglichkeit der Fehlerreproduktion ist auf jeden Fall besser als die Software abstürzen zu lassen.

    Was verstehst du eigentlich unter einem Fehler ? Eine falsche Berechnung ? Ein unnormales Verhalten bei unnormalen Eingaben ? Ein unnormales Verhalten bei normalen Eingaben ? Ein Windows spezifischer Fehler ? Oder ein C++ typischer Fehler ?



  • Bitte ein Bit schrieb:

    Anonsten: Lieber eine Software crashen lassen inkl. vernünftigen Crashdump, ale eine Fehlermeldung die weder dem Benutzer noch dem Entwickler hilft

    Dem kann ich leider überhaupt nicht zustimmen, denn es widerspricht auch der Definition von robuster Software.

    Eine sinnvolle Fehlermeldung, welche eine eindeutige Fehlernummer beinhaltet, sowie eine verbesserte Möglichkeit der Fehlerreproduktion ist auf jeden Fall besser als die Software abstürzen zu lassen.

    Ne.
    Ein Programm nach einem Fehler weiterlaufen zu lassen, der so übel riecht, dass er eigentlich niemals hätte passieren sollen... DAS widerspricht der Definition von robuster Software 😉



  • @hustbaer
    Nein das meinte ich doch überhaupt nicht !!!

    Warum sollte ich bei einem schwerwiegenden Fehler das Program nicht beenden wenn es dem Benutzer schaden würde ?
    Warum sollte ich bei einem Program ala Word im Fall eines schwerwiegenden Fehler nicht vorher versuchen das Dokument abzuspeichern bevor ich das Programm terminiere ?
    Warum sollte eine Berechnungssoftware abstürzen, wenn der Benutzer die Software mit unsinnigen Daten füttert, anstatt das die Software eine Meldung der Form bringt: "Lieber Benutzer, deine Eingaben sind scheiße !" ?

    Ich denke das es von Fehlertyp und dem System abhängt welche Art von Fehlerbehandlung man machen kann. Der Begriff Fehler ist hierfür viel zu groß. Und beim Martin habe ich halt den Verdacht das er mit seiner Aussage Windows spezifische Fehler meinte und nicht Fehler im Allgemeinen. Bsp:

    HWND hWnd = CreateWindow(....);		// CreateWindow kann auch NULL zurückliefern
    ...
    PostMessage(hWnd, WM_NULL, 0, 0);
    

    Und vielleicht macht es hier Sinn das Programm abstürzen zu lassen. Aber macht es auch im folgenden Sinn ?

    void DoSomething(const CHAR* Name)
    {
      CHAR MyName[16];
      ...
      sprintf(MyName, Name);
    }
    ...
    DoSomething("Theodor von Gutenberg");
    

    Deswegen ziehe ich eher das Konzept des Exception Handling vor. Man kann dann im Fehlerfall immer noch entscheiden ob man das Program sauber (!!!) terminieren/herunterfahren will oder ob man mit dem Fehler (mit Hilfe einer Fehlerkorrektur) leben kann.


  • Mod

    Gerade der zweite Fall macht absolut Sinn einen Crash herbei zuführen...

    Woher weißt Du was die Anwednung auf dem Stack/Heap vernichtet hat und ob Deine "gut gemeinten Versuche" die Daten des Anwenders noch "zu retten" nicht genau im Gegenteil enden?

    Beides snd aus meine Sicht Fehler des Entwicklers und führen zum Crash.

    Das ein Fenster nicht angelegt werden kann, wird onst "soft" abgefangen und endet evtl. doch im Beenden des Programmes... aber eben weich und gesteuert mit sichern der Daten.

    Definiere Fehler im Allgemeinen:
    - Ein Programmiererfehler
    -- unzureichende Fehlerprüfung
    -- Bufferoverflow
    -- Falsche Parameter
    - Ein "harter" Fehler in der Ausführung
    -- Ein nicht zu erwartender I/O Fehler. DB Verbindung reißt ab etc.
    -- Kein Speicher mehr, keine GDI Handles.
    -- Eine DLL die installiert sein müsste ist nicht da oder hat eine falsche Version
    - Ein "weicher" Fehler bei der Ausführung
    -- Datei nicht gefunden (weil user sich vertippt hat)
    -- Datensatz nicht gefunden
    - Anwednungsfehler
    -- Benutzer gibt Schrott ein.

    Eigentlich führen die ersten beiden Kategorien bei mir sofort zum Programm-Abbruch und zu einem Dump und zum Reort über WER.



  • Es ist jetzt viel gesagt worden über alle möglichen Fehler und wie man als Programmentwickler damit umgehen soll. Es zeigen sich dabei auch unterschiedliche Programmierstile. Alle diese Programmierstile sind gerechtfertigt, wenn sie dem Ziel 'stabiles Programm' dienen.

    Grundsätzlich: Der Anwender hat damit nichts zu tun - er schreit wenn etwas nicht läuft wie er erwartet, fragt dann den Programmentwickler und fordert Abhilfe. Das ist sein gutes Recht, wenn er für die Software bezahlt hat oder für die Programmpflege weiter bezahlt.

    Also ist in jedem Fall der Programmentwickler gefragt. ER muss wissen, wie man Fehler möglichst vermeidet und wenn sie auftreten geeignete Methoden haben, wie man sie findet und schnell behebt. Das gehört zu jeder professionellen Programmierung notwendig dazu. Fehler können schliesslich Geld kosten! 😮 Ich denke z.B. an die Software für ein Walzwerk, wo Stahlbleche mit vorgeschriebener Dicke gefordert sind. Weicht diese Dicke vom Kundenauftrag ab, so ist die Produktion der Stahlbleche mit erheblichen Folgekosten im Eimer. In anderen Branchen gibt es ähnliches.

    Das Thema ist und bleibt in der Softwarentwicklung aktuell. Da kommt niemand drum herum!



  • Bitte ein Bit schrieb:

    Deswegen ziehe ich eher das Konzept des Exception Handling vor. Man kann dann im Fehlerfall immer noch entscheiden ob man das Program sauber (!!!) terminieren/herunterfahren will oder ob man mit dem Fehler (mit Hilfe einer Fehlerkorrektur) leben kann.

    Zu versuchen ein Programm sauber zu beenden, wenn man nicht sicher sein kann welche Invarianten alle schon verletzt sind, ist ein Glücksspiel. Und mMn. der ganz falsche Weg.
    Log-Eintrag schreiben, Crash-Dump schreiben, Prozess killen.


  • Mod

    hustbaer schrieb:

    Zu versuchen ein Programm sauber zu beenden, wenn man nicht sicher sein kann welche Invarianten alle schon verletzt sind, ist ein Glücksspiel. Und mMn. der ganz falsche Weg.
    Log-Eintrag schreiben, Crash-Dump schreiben, Prozess killen.

    ACK!



  • *hustbaer den Begriff Korrektheit zuspielen*



  • Zeus schrieb:

    *hustbaer den Begriff Korrektheit zuspielen*

    JA!

    Es fehlt aber noch eine weitere schwer zu findende Fehlermöglichkeit: Das Programm läuft anstandslos durch ohne irgendwelche Verletzungen und ohne Crash, nur es erzeugt falsche Ergebnisse. Irgendwo in der vorher durchlaufenen Kette von Bearbeitungsschritten ist vielleicht mit einem falschen - aber zulässigen - Index etwas anderes als erwartet zugewiesen worden. Gerade diese Fehler sind äusserst schwer aufzudecken. Klingt banal, doch kann verhehrende Wirkung haben. So hat einmal ein von mir entwickeltes Programm zur Trassierung von Eisenbahn-Neubaustrecken in einer besonderen Situation 10 cm zu wenig Schotter unter einem Gleis berechnet. Erst der Mann auf der Schottermaschine auf der Neubaustrecke hat diesen Fehler bemerkt und Alarm geschlagen. Im Programm war nur eine Zeile falsch.

    Ich ergänze diesen Hinweis, um zu zeigen dass ein Programmentwickler mit einer Vielzahl von Fehlermöglichkeiten rechnen und darauf eingestellt sein muss, auch mit solchen die hier noch nicht genannt worden sind.



  • @hustbaer:

    Alles klar. 😞

    Ich glaube das jeder, der nicht einen probabilistischen Algorithmus programmmiert, und auf indeterministischen Daten arbeitet, seinen Sachen packen und von der Informatik einen Bogen machen sollte.

    @Martin:
    Ich glaube wir reden hier gewaltig aneinander vorbei. 😞 Ich verstehe einfach deinen Spruch "Lieber deine Software crashen lassen als eine Fehlermeldung!" nicht. Denn meines Erachtens kommt es immer auf den Fehlertyp an.

    Ich probiere es daher nochmal mit Code-Beispielen mit unterschiedlichen Fehlerbehandlungen:

    Beispiel 1:

    // Annahme: Kein Name ist länger als 256 Zeichen 
    void DoSomething(const CHAR* Name)
    {
      CHAR MyName[256] = {0};
      ...
      sprintf(MyName, Name);
    }
    

    Beispiel 2:

    // Annahme: Kein Name ist länger als 256 Zeichen 
    bool DoSomething(const CHAR* Name)
    {
      CHAR MyName[256] = {0};
      ...
      if ((strlen(Name) + 1) > sizeof(MyName))
      {	
    	MessageBox(NULL, "Fehler 100: Namen mit mehr als 256 Zeichen werden nicht unterstützt!", "ABC", MB_OK);
    	// throw MyOverflowException(...)
    	return false;
      }
      sprintf(MyName, Name);
    }
    

    Beispiel 3:

    // Annahme: Kein Name ist länger als 256 Zeichen 
    void DoSomething(const CHAR* Name)
    {
      CHAR MyName[256] = {0};		
      ...
      _snprintf(MyName, sizeof(MyName), Name);
    
    }
    

    Was ist deines Erachtens die bessere Lösung ?

    Beispiel 1 stürzt im Spezialfall ab und stellt unter Umständen ein Sicherheitloch da. Die anderen Beispiele stürzen nicht ab, können aber trotzdem ein Fehlverhalten erzeugen wenn beispielsweise der Speicher MyName nur 16 Zeichen groß ist.

    Interresanterweise ist bei gewissen Regelungen über Abrechnungen (vom Bundesamt bzw. von der DIN Stelle) nur Codebeispiel 2 (vielleicht auch noch 3) korrekt. Dort wird klar definiert: Ein Name ist exakt 8 Zeichen groß. Peng ! Und wenn ein Benutzer einen längeren Namen hat, hat er Pech gehabt.

    Etwas möchte ich aber noch festhalten. Wenn bei meinem Programmen ein "harter" Fehler auftaucht, dann stürzt auch meine Software ab. Und ja, ich gebe es jat zu, bei einigen Befehle der WinAPI schaue ich nicht auf den Rückgabewert. Die Befehle erwiesen sich, bitte alle Windows-Trolle mal weghören, als (einigermaßen) stabil und fehlerfrei.

    Ansonsten gebe ich berniebutt Recht:
    Es ist jetzt viel gesagt worden über alle möglichen Fehler und wie man als Programmentwickler damit umgehen soll. Es zeigen sich dabei auch unterschiedliche Programmierstile. Alle diese Programmierstile sind gerechtfertigt, wenn sie dem Ziel 'stabiles Programm' dienen.

    @berniebutt:
    Ich lernte erst den Begriff Testreihe auf der Arbeit schätzen weil man damit einigermaßen sicherstellen kann das vorgenommene Änderungen am Program keine anderen Ergebnisse liefern.



  • Bitte ein Bit schrieb:

    @hustbaer:

    Alles klar. 😞

    Ich glaube das jeder, der nicht einen probabilistischen Algorithmus programmmiert, und auf indeterministischen Daten arbeitet, seinen Sachen packen und von der Informatik einen Bogen machen sollte.

    Kannst du das ganze nochmal so schreiben dass ich verstehen kann was du mir damit sagen willst?



  • hustbaer schrieb:

    Bitte ein Bit schrieb:

    @hustbaer:

    Alles klar. 😞

    Ich glaube das jeder, der nicht einen probabilistischen Algorithmus programmmiert, und auf indeterministischen Daten arbeitet, seinen Sachen packen und von der Informatik einen Bogen machen sollte.

    Kannst du das ganze nochmal so schreiben dass ich verstehen kann was du mir damit sagen willst?

    Ist doch egal, ob du oder ich das verstehen. Er ist oder wird als Informatiker Chefentwickler und macht dann seine Vorgaben für andere, die das umsetzen sollen! 😃 Sobald er in dieser Position angelangt ist, deckelt er einfach seine Programmierer. 😡



  • hustbaer schrieb:

    Bitte ein Bit schrieb:

    @hustbaer:

    Alles klar. 😞

    Ich glaube das jeder, der nicht einen probabilistischen Algorithmus programmmiert, und auf indeterministischen Daten arbeitet, seinen Sachen packen und von der Informatik einen Bogen machen sollte.

    Kannst du das ganze nochmal so schreiben dass ich verstehen kann was du mir damit sagen willst?

    Du weist nicht was du hast + Du weisst nicht wie du etwas tun willst = Was ist das Ergebnis? berniebutt sowas programmierst du - Du muss viel Spaß haben!!



  • @berniebutt und hustbaer
    Tut mir leid, ich wollte hier nicht arrogant erscheinen. 😞

    Bloß was mich ein wenig störte war, das es mir so rüber kommt als es gibt nur eine Art von Fehlerbehandlung: Log-Eintrag schreiben, Crash-Dump schreiben, Prozess killen und sonst nix. Und als ich dann eine Alternative aufbot, da wurde mir unterstellt, da müsse man ja auf korrupten Daten arbeiten. Und das empfand ich als leicht beleidigend. 😞 Denn da suchte man wieder in den Krümeln nach Fehlern und schoss mit Spatzen auf Kanonen. 😞

    Und genau deswegen reagierte ich auch so mit dem Spruch das Leute welche mit zerschossenen Daten arbeiten eigentlich nix in der Informatik zu suchen hätten. Es macht doch Null Sinn etwas Zerschossenes retten wollen und dementsprechend fand ich auch den Kommentar dazu sinnlos. Aber in vielen Fällen kann man diesen Fall schon vorher abfangen und dementsprechend darauf reagieren so wie es ein Exe Kompilat schon automatisch tut, wenn es eine benötigte DLL nicht findet. Aber ich fürchte das will hier keiner sehen. 😞

    So ich beende jetzt die Diskussion bevor das Ganze noch in einem Flamewar endet.



  • Bitte ein Bit schrieb:

    Beispiel 2:

    // Annahme: Kein Name ist länger als 256 Zeichen 
    bool DoSomething(const CHAR* Name)
    {
      CHAR MyName[256] = {0};
      ...
      if ((strlen(Name) + 1) > sizeof(MyName))
      {	
    	MessageBox(NULL, "Fehler 100: Namen mit mehr als 256 Zeichen werden nicht unterstützt!", "ABC", MB_OK);
    	// throw MyOverflowException(...)
    	return false;
      }
      sprintf(MyName, Name);
    }
    

    Interresanterweise ist bei gewissen Regelungen über Abrechnungen (vom Bundesamt bzw. von der DIN Stelle) nur Codebeispiel 2 (vielleicht auch noch 3) korrekt.

    strlen,... sucht das nicht auch nach einer nullterminierung?


Anmelden zum Antworten