"exit()" in einer lib?!



  • exit(0x123); schrieb:

    Oder sollte man das dem Programmierer des Hauptprogramms überlassen und einen Fehlercode zurückgeben?

    fjeden digga!



  • Wenn eine Lib im Fehlerfall exit() aufruft, würde ich sie auf keinen Fall benutzen. Das wäre höchstens okay, wenn sie feststellt, dass die Laufzeitumgebung hoffnungslos zerschossen ist (d. h. Bedingungen auftreten, die nicht auftreten können sollten), und dafür gibt es assert().



  • TyRoXx schrieb:

    Ne, das geht viel "besser":

    #include<string.h>
    #include<stdio.h>
    #define SUCCESS 1
    #define FAIL 0
    int my_lib_fn
    (int n){
       /* der Benutzer kriegt richtig in die Fresse,
       wenn er etwas falsch macht */
       if(n<0)
       {  memset(&n + 5, 0, 13);
          return SUCCESS; }
       unsigned long real_n = n;
       printf("%d\n", real_n);
       return SUCCESS;
    }
    void main(){
       my_lib_fn(-1);
       return -12;
    }
    

    Hä? Inwiefern beantwortet das meine Frage?

    naturally schrieb:

    fjeden digga!

    Auch hallo 🙄


  • Mod

    seldon schrieb:

    und dafür gibt es assert().

    Und da haben wir schon ein Beispiel für eine Bibliotheksfunktion (hier die Standardbibliothek), die sinnvoll und gewollt das Programm beendet (hier mit abort statt exit, aber daran wollen wir uns mal nicht aufhängen).

    Ich konkretisiere mal meine obige Antwort: Wenn die Bibliothek irgendwelche Fehlerbehandlungssachen macht (vorstellbar wäre zum Beispiel ein Exceptionsframework in C), dann kommt man schnell zu Beispielen, bei denen ein Programmabbruch durch Bibliothekscode sinnvoll und gewünscht ist.



  • Naja, im Fall von assert ist jetzt schon wichtig, dass es keine Funktion, sondern ein Makro ist, das nur in Debug-Builds auftaucht. Wenn die Bedingung innerhalb eines asserts auftritt, ist das ein Bug, und der Zustand, in dem sich das Programm befindet, ist nicht mehr konsistent. Dann ist ein Abbruch sinnvoll, aber keine Lösung des eigentlichen Problems.

    Mit Exceptionframeworks in C habe ich mich nie im Detail auseinandergesetzt. Mag sein, dass man ein solches Vorgehen da verteidigen kann.



  • GTK+ schreibt eine fette Fehlermeldung auf stderr, macht danach aber normal weiter (also mehr oder weniger zufälliges Verhalten).

    Ich denke, das ist die richtige Variante, denn niemand legt sich eine extra Debug-Version einer Bibliothek hinzu und Abstürzen im Release ist dann schon etwas zu hart, nur weil irgendwo ein unbedeutender Bug ist.



  • exit() in einer lib?!

    auf keinsten!



  • Naja, ich meinte hier eher solche Probleme, die im schlimmsten Fall das ganze Programm zum absturz bringen.
    z.b. irgendwelcher müll mit malloc und free, da kann echt viel passieren.

    wäre es nicht besser, man beendet das programm mit exit (nebenbei kümmert sich ja exit() auch darum, dass allokierter speicher freigegeben wird, file-handles geschlossen werden usw.) und hinterlässt keine speicherlecks, als wenn man das programm einfach abstürzen lässt?



  • Eine vernünftig programmierte Lib stürzt nicht ab.
    🙄



  • kümmert sich ja exit() auch darum, dass allokierter speicher freigegeben wird, file-handles geschlossen werden usw.

    Das macht das Betriebssystem.

    z.b. irgendwelcher müll mit malloc und free, da kann echt viel passieren

    Nein, da kann garnichts passieren. Ausser: du benutzt es falsch. Und das ist ein Bug. Software sollten keine Bugs enthalten bzw. sollten gefixet werden.

    wäre es nicht besser, man beendet das programm mit exit

    Nein, waere es nicht. Besser ist es, den Programmierer die Chance zu geben, auf den Fehlerfall zu reagieren.



  • knivil schrieb:

    kümmert sich ja exit() auch darum, dass allokierter speicher freigegeben wird, file-handles geschlossen werden usw.

    Das macht das Betriebssystem.

    Nein. Wenn ich einfach Speicherplatz allokiere und dann das Programm beende, führt das zu Memory-Leaks...

    Mag sein, dass das Betriebssystem den RAM-Speicher überwacht, damit kein Speicherplatz einfach so überschrieben werden kann, aber das Betriebssystem freed garnix.



  • exit(0x123); schrieb:

    knivil schrieb:

    kümmert sich ja exit() auch darum, dass allokierter speicher freigegeben wird, file-handles geschlossen werden usw.

    Das macht das Betriebssystem.

    Nein. Wenn ich einfach Speicherplatz allokiere und dann das Programm beende, führt das zu Memory-Leaks...

    Mag sein, dass das Betriebssystem den RAM-Speicher überwacht, damit kein Speicherplatz einfach so überschrieben werden kann, aber das Betriebssystem freed garnix.

    Genau Null Ahnung du hast, digg0r.



  • Ok, klär mich auf was diesen Punkt betrifft.

    Und hör endlich mit diesem peinlichen "diggr" auf.

    Also so hab ich das gelernt:
    Der gesamte RAM wird in gleich große Stücke aufgeteilt, so 4KB usw. Irgendwo im Betriebssystem gibt es ein (char-)Array, das genau GrößeDesRams/4KB - Teile hat.

    Wenn nun ein Programm Speicherplatz alloziert wird, wird eine bestimmte Stelle in dem Array auf 1 gesetzt (bzw. sonstig markiert), das bedeutet, dass dieser Speicherplatz gerade benutzt wird und auf keine Fall einem anderen Programm zugwiesen werden darf.

    Wenn ich nun free() aufrufe, wird in das Array wieder 0 eingetragen, d.h. der Speicherplatz ist freigegeben und darf neu beschrieben werden.

    Wenn ich (der Programmierer!) kein free() aufrufe, dann wird der Speicherplatz auch nicht freigegeben (dies geschieht dann nach einem Neustart, wenn wieder alle Array-Elemente auf 0 sind).

    z.b.
    Ich habe 4 GB-RAM (=4194304 KB), dann könnte das so aussehen

    #define ARRAY_SIZE (4194304/4) // die Größe des Rams in KB durch 4 KB
    char memory[ARRAY_SIZE];
    
    // jetzt werden die ersten 4 KB allokiert:
    memory[0]=1; // erstes 4kb-großes segment ist belegt und darf nicht durch andere programme benutzt werden.
    

    Das ist natürlich stark vereinfacht, aber so in etwa gehts.



  • ...



  • Swordfish schrieb:

    Moi, süß! 🙂

    Achso... ja das erklärt natürlich alles 🙄

    wenn ihr keine lust habt, euch hier an gescheiten gesprächen zu beteiligen, dann lasst es doch einfach!



  • Geil wie er nicht auf digga klarkommt :p


  • Mod

    Das Betriebssystem (wenn's nicht gerade aus den 70er Jahren ist oder auf einem Mikorcontroller läuft) weiß aber, welcher Prozess welche Speicherseiten belegt hat und welche Dateien er offen hält. Wenn der Prozess beendet wird, kann (und wird) daher alles sauber freigegeben.

    Trotzdem ist das gute Praxis, auch im Fehlerfall sauber aufzuräumen.

    Es sind auch Ressourcen denkbar, von denen das Betriebsystem nichts weiß (weil es nicht direkt damit zu tun hat), die auch freigegeben werden müssen. Bei allen Arten von Ressourcen kann man dann die gleichen Programmmuster benutzen, um eine saubere Freigabe zu garantieren.



  • exit(0x123); schrieb:

    Und hör endlich mit diesem peinlichen "diggr" auf.

    ey oldär, exit(0x0815) ist aber nicht peinlich oda watt?
    🙄



  • digga++ gemobbt schrieb:

    ey oldär, exit(0x0815) ist aber nicht peinlich oda watt? 🙄

    Nicht annähernd so peinlich wie "ey oldär," "digg0r" und "lolz0r." Du klingst wie die Karikatur eines Skriptkiddies aus einem Gamer-Forum. Lass das.

    Was den eigentlichen Thread angeht: alles, was auf Betriebssystemebene mit einem einzelnen Prozess (und nur diesem) zusammenhängt, wird bei Prozessende eingerissen, davon kann man ausgehen. Dazu zählt der Freestore (Heap) und die relevanten Teile der Page Table, offene Dateideskriptoren und derlei Dinge mehr, die nach Prozessende stumpf keinerlei Bedeutung mehr haben. Die Information, was Filehandle 16 in Prozess 1234 mal war, ist nach dessen Ende schlicht von niemandem mehr verwendbar. Ob allerdings die Daten im zugehörigen Buffer noch auf die Platte geschrieben werden, ist eine andere Frage; wenn der Prozess hart runtergeht, kann so was von System zu System verschieden sein.

    Es gibt allerdings Dinge, die auf Betriebssystemebene nicht eindeutig einem Prozess zuzuordnen sind, und diese werden dann auch nicht aufgeräumt. Dazu zählen beispielsweise temporäre Dateien, Kindprozesse, shared memory und Dinge, die dein Programm in anderen Prozessen ausgelöst haben mag. Wenn du beispielsweise eine Netzwerkverbindung zu einem Server hältst und dein Prozess einfach abschmiert, wird diese Verbindung auf der Gegenseite noch eine Weile offen bleiben (bis zum Timeout). Im Umgang mit solchen Dingen ist dann auch entsprechende Vor- und Umsicht angebracht -- und da du als Bibliothek darauf vorbereitet sein musst, in Programmen benutzt zu werden, die mit derlei Dingen umgehen, ist ein harter Abbruch per Design da nicht sinnvoll.

    Wenn du einmal undefiniertes Verhalten ausgelöst hast und feststellst, dass der Zustand des Programms hoffnungslos zerschossen ist, dann macht eine Notbremse die Sache auch nicht mehr schlimmer, aber gelöst werden muss das Problem natürlich, indem kein undefiniertes Verhalten mehr ausgelöst wird -- also per Bugfix.



  • seldon schrieb:

    Nicht annähernd so peinlich wie "ey oldär," "digg0r" und "lolz0r." Du klingst wie die Karikatur eines Skriptkiddies aus einem Gamer-Forum. Lass das.

    yo. amen, mann.


Anmelden zum Antworten