atexit() zurück zur main()



  • Hallo

    Habe ein Problem mit atexit(). Und zwar möchte ich miten im Code mit atexit(main) zu main springen. Doch funktionieren tuts nicht! Erst wenn ich atexit(main()) schreibe! Was aber eine Compilerwarnung ausspuckt. Jetz meine Frage warum dass?



  • Die Warnung wird daher kommen, dass die Rückgabe von main(), also ein int, in einen Funktionszeiger gecastet wird. Dass main nicht in atexit passt, liegt daran, dass atexit einen void(*)(void) erwartet und main diese Signatur nicht haben darf.

    Dein Vorhaben wird auf diese Weise auch aus anderen Gründen nicht funktionieren. Wahrscheinlich wäre es sinnvoller, um das Programm ein Skript zu schreiben, das das Programm immer wieder ausführt.



  • Aber wenn ich atexit(main()); schreibe funktioniert es.!



  • blackh schrieb:

    Aber wenn ich atexit(main()); schreibe funktioniert es.!

    Aber nicht wenn du das oft hintereinander machst 😉

    Edit:
    Wobei das auch mit atexit(main) nicht sonderlich oft funktionieren würde, wenn es denn überhaupt funktionieren würde. (oO)

    Was spricht eigentlich gegen eine Schleife in der Main und ein Verzicht auf exit()?



  • atexit(main()) ruft main() auf, bevor atexit erreicht wird. Wenn main nicht zurückkehrt, ist das nie der Fall - in dem Moment, in dem es geschieht, fliegt dir das Ganze aber auseinander. Gehe ich recht in der Annahme, dass du irgendwo im Code etwas wie

    atexit(main());
    exit(0);
    

    stehen hast? Dort wird atexit im Zweifel nie erreicht.

    Übrigens kriegst du damit früher oder später Stack-Overflows.



  • Es soll also sowas sein, wie "Bei jedem erdenklichen Fehler wird von vorn angefangen".
    Also

    int main(){
       atexit(main);
       tuwas();
    }
    

    Nette Idee.
    (Warnung: In C++ ist es verböten, die main zu callen, also bitte nicht dahin übertragen,)

    Der Typ der main paßt nicht. Das würde ich vielleicht so wegmachen.

    void mainCaller(){
       main();
    }
    int main(){
       atexit(mainCaller);
       tuwas();
    }
    

    Oder

    void mainCaller(){
       atexit(mainCaller);
       mainCaller();
    }
    int main(){
       mainCaller();
    }
    

    Das geht alles davon aus, daß erstens die Reihenfolge der per atexit gepushten Calls in umgekehrter Reihenfolge abgearbeitet wird (ist klar) und zweitens, daß es nicht eine simple Rückwärts-For-Schleife ist, sondern eine while(atExitStackHead!=NULL)... und sie erlaubt, daß man während atexit noch was hinzufügt, das dann auch vorrangig abgearbeitet wird. KA, wie das in C vom Standard spezifiziert ist. Ältere Compiler machen es nicht. Ich vermute, daß die neueren Compiler es alle machen.

    Dann hätte ich folgende Idee:

    void theRealMain(){
       atexit(theRealMain);
       theRealRealMain();
    }
    int main(){
       theRealMain();
    }
    


  • Das Problem, in das man damit läuft, ist, dass der mehrfache Aufruf von exit innerhalb eines Programms undefiniert ist. Man kann zwar einen maincaller mit atexit eintragen, aber wenn main dann erneut zu einem Aufruf von exit kommt, hast du ein Problem.

    ISO/IEC 9899:1999 7.20.4.3 (2) schrieb:

    The exit function causes normal program termination to occur. If more than one call to the exit function is executed by a program, the behavior is undefined.



  • Da ich bezüglich Schleifen hier im Forum schon viele Varianten gesehen habe, erst mal eine Frage:
    Kann der Beitragsersteller seinen Code in 20 Zeilen zusammenfassen und, wenn etwas Besonderes bei seinem Code gefordert ist, dies in einem kurzen Kommentar dazu schreiben?

    MfG f.-th.


  • Administrator

    Wie wäre es mit einem setjmp und longjmp ? Gleich als erstes nach dem Start wird ein setjmp aufgerufen und der jmp_buf global zur Verfügung gestellt. Damit kann man von überall her wieder zurück an den Anfang gehen.

    Grüssli



  • Dravere schrieb:

    Wie wäre es mit einem setjmp und longjmp ?

    Schon die Verwendung von goto (für Sprünge innerhalb einer Funktion) gilt im Allgemeinen als schlechter Programmstil - Sprünge quer durch das gesamte Programm sind da noch schlimmer.
    Wir sollten uns lieber erklären lassen, was blackh mit seiner Konstruktion eigentlich beabsichtigt - und dann nach saubereren Möglichkeiten suchen, sein Problem zu lösen.


  • Administrator

    CStoll schrieb:

    Schon die Verwendung von goto (für Sprünge innerhalb einer Funktion) gilt im Allgemeinen als schlechter Programmstil - Sprünge quer durch das gesamte Programm sind da noch schlimmer.

    Aber auch goto soll man nicht komplett ausschliessen.

    CStoll schrieb:

    Wir sollten uns lieber erklären lassen, was blackh mit seiner Konstruktion eigentlich beabsichtigt - und dann nach saubereren Möglichkeiten suchen, sein Problem zu lösen.

    Da stimme ich dir allerdings vollständig zu.

    Grüssli


Anmelden zum Antworten