main() rekursiv aufrufen?



  • Es gibt keinen wirklich schluessigen Grund. Es ist deshalb verboten damit Implementierungen am Anfang von Main initialisierungen vornehmen koennen. Nur ist es ja kein Problem diese in eine andere Funktion zu legen und von dort aus dann main aufzurfen (VC++ verwendet zB _CrtMainStartup oder so).

    Es gibt aber keinen Grund warum man das unbedingt tun muss, deshalb ists eigentlich kein Thema.

    In C ist es zB erlaubt.



  • Da quote ich mal jemanden :

    Jemand schrieb:

    Think about a normal function call(one that doesn't call main). First the program may load the stack with values, jump to the function address, possibly load more values on the stack execute some code and then return...When the function returns it frees up all of its stack resources...Hence the term local variables...Local to the function, stored on the stack...Now a main function only returns when the program exits...So each time you call main you load up the stack with its associated values only freeing them all(all of main's) when the program exits....Do you now see why its not a good idea?



  • @Felixxx Jetzt bin ich überzeugt 🙂

    Edit lieber so:

    void foo(){
    	static int b = 0;
    	cout << ++b << "\n"; 
    }
    
    int main(){ 
        while(1)
    		foo(); 
    }
    


  • Ich bin noch nicht überzeugt. Warum kann der Compiler nicht intern in einer anderen Funktion starten und dann main aufrufen? So viel Flexibilität ist bei C++ nichts aussergewöhnliches.

    Aber ich hinterfrage zu viel. Warum HighLigerBiMBam drei Posts geschrieben hat, ohne etwas brauchbares auszusagen finde ich auch mehr als fragwürdig.



  • Weil ich das Thema interessant fand und aus tiefster Überzeugung Spammer bin. Und anscheinend kann der Compiler dies nicht auslagern.

    Edit: Ich kann derzeit auch nur schwer beurteilen, ob dieses "Feature" ein Vor- oder Nachteil gegenüber C ist. Aber die Erklärung hat mich geholfen zu verstehen warum in C++ dies nicht gemacht wird. Dies erklärt aber nicht warum man es nicht in eine Funktion Compilerseitig erstellt.



  • also zunächst mal ist es erlaubt, auch in C++!
    Im Standard steht ausdrücklich "shall not" und nicht "must not".
    Es ist also lediglich eine Empfehlung main nicht aufzurufen.

    Die Erklärung, dass main lokale Variablen erst bei Programmende freigibt ist Dünnes.
    main wird genau wie jede andere C-Funktion über die C Calling Convention aufgerufen. Lokale Variablen und Parameter liegen auf dem Stack und werden beim return wieder aufgeräumt.

    Die main Funktion stürzt aus dem gleichen Grund ab, aus dem auch jede andere Funktion mit unendlicher Rekursion abstürzt: Stack Overflow.

    Da bei einer unendlichen Rekursion das return NIE erreicht wird, wird auch der Stack nicht aufgeräumt.
    Allerdings kann auch bei endlicher Rekursion ein Stack Overflow auftreten, wenn die Rekursion einfach zu tief ist.



  • Okay, das wollte ich wissen, dankeschön^^



  • Rekursion -> Stack Overflow -> klar, aber warum ist bei der Rekursion von Main der Stack so viel schneller voll, als wenn ich es in eine Funktion auslagere? Wieviel zusätzliche Initialisierungsarbeiten leistet die main?



  • DrakoXP schrieb:

    also zunächst mal ist es erlaubt, auch in C++!
    Im Standard steht ausdrücklich "shall not" und nicht "must not".
    Es ist also lediglich eine Empfehlung main nicht aufzurufen.

    Nein, "shall" bedeutet im C++-Standard schon "muss" (sofern sich die Implementierung an den Standard hält und portables Programmieren ermöglichen will). Den Ausdruck findest du immer wieder.

    DrakoXP schrieb:

    main wird genau wie jede andere C-Funktion über die C Calling Convention aufgerufen.

    Der Standard sagt, die Linkage von main() sei implementation-defined. Dem entnehme ich, dass die Implementierungsabhängigkeit auch auf die Calling Convention zutrifft.

    DrakoXP schrieb:

    Die Erklärung, dass main lokale Variablen erst bei Programmende freigibt ist Dünnes. [...] Lokale Variablen und Parameter liegen auf dem Stack und werden beim return wieder aufgeräumt.

    Ja, und zufällig leitet ein return in main() das Programmende ein.

    Incocnito schrieb:

    Okay, das wollte ich wissen, dankeschön^^

    Vergiss das lieber wieder, es ist nämlich zu einem grossen Teil falsch.



  • Was hindert dich daran, es selber nachzuschauen?
    Laut Standard: nichts
    Laut g++: Nichts, das wird in _GLOBAL__I_main erledigt.
    Laut deinem proprietären visuellen Compiler: wahrscheinlich alles (ich weiss es nicht)

    Klar, der Standard erlaubt es, weshalb das Programm von Incocnito funktioniert. Aber benutzen sollte man es dennoch nicht.



  • Hmm wenn du meinst, Nexus. Hat sich nur so schön plausibel und einfach angehört^^

    ps. Du hast jetzt schon 8000 Beiträge, Respekt 😉



  • 😑 schrieb:

    Was hindert dich daran, es selber nachzuschauen?
    Laut Standard: nichts
    Laut g++: Nichts, das wird in _GLOBAL__I_main erledigt.
    Laut deinem proprietären visuellen Compiler: wahrscheinlich alles (ich weiss es nicht)

    Klar, der Standard erlaubt es, weshalb das Programm von Incocnito funktioniert. Aber benutzen sollte man es dennoch nicht.

    hehe das deutlich früher abrauchen lag am debug mode 🙄 Macht keinen Unterschied im Release... Alles klar danke.



  • Nur der Vollständigkeit halber:
    Verlangt Rekursion eigentlich zwingend eine Abruchbedingung, oder ist rein theoretisch auch das gezeigte Beispiel eine Rekursion?

    (Ich meine das eher im mathematischen Sinne; ist ja klar, dass eine Programmfunktion ohne Abbruchbedingung wohl keinen Sinn ergibt, und da meine ich nicht einen stack overflow...)



  • Verstehe dich nicht o.0

    Der Compiler kann dich schlecht dazu zwingen eine Abbruchbedingung zu benutzen, also kannst du es natürlich tun.
    Was hat eine Endlos-Schleife mit Mathematik zu tun?



  • Felixxx schrieb:

    Was hat eine Endlos-Schleife mit Mathematik zu tun?

    Berechenbarkeit. Also alles.

    @minastaros eine Endlosrekursion ist Äquivalent zu einer endlosschleife, beide sind nicht berechenbar.



  • Berechnbarkeit ? Was meinst Du ? Zum Beispiel Grenzwerte?



  • Probiert das doch mal auf deutlich verschiedenen Betriebssystemen.
    Das Beispiel sollte von der Speicherausstattung und Speicherverwaltung abhängig, eine unterschiedliche Anzahl von Wiederholungen als Ergebnis haben.

    Die das getestet haben haben ja das Limit 2^16 - oder ist das in den Standards garantiert 😕

    MfG f.-th.



  • otze schrieb:

    @minastaros eine Endlosrekursion ist Äquivalent zu einer endlosschleife, beide sind nicht berechenbar.

    Schon wieder? Das hatten wir doch gerade erst. Berechenbarkeit ist eine Eigenschaft von Funktionen. Es ist sinnlos zu sagen, ein Programm sei berechenbar oder nicht berechenbar.



  • Ich meine den Begriff der Rekursion als mathematisches Prinzip. Soweit ich sie kenne, ist sie ja eigentlich dadurch definiert, dass sie irgendwann abbricht und nur dadurch funktioniert wie z.B. Quicksort oder Fakultäten...

    Kenn mich da nicht so aus, daher meine Frage, ob es in der Mathematik eben so etwas gibt wie eine rein theoretische "infinite Rekursion".

    Klar, dass man eine Endlosschleife programmieren kann und daher auch eine Funktion, die sich immer wieder selbst aufruft, bis der Speicher alle ist. Aber ich denke eben nicht, dass man hier wirklich von Rekursion spricht im Sinne eines bestimmten Algorithmus'.

    (Ich geb zu, das ist etwas weit weg vom Ursprungsthema, aber hat mich gerade interessiert...)



  • DrakoXP schrieb:

    Im Standard steht ausdrücklich "shall not" und nicht "must not".

    Lern bitte richtig Englisch. "Shall" ist am besten mit "sei" zu übersetzen, d.h. die Autoren der Norm hatten die freie Wahl und haben sich für eine bestimmte Festlegung entschlossen und diese muß nun eingehalten werden.


Anmelden zum Antworten