int main;


  • Mod

    idontgotit schrieb:

    Was meinst du damit:

    Es darf aber funktionieren, wenn es andere mains gibt!

    Gloable Funktionen, die "main" heissen und "int" zurückgeben oder etwas anderes?
    Letzteres ist in meinem Verständnis unmöglich, da ein (gehostetes) Programm ein "int main(irgendwas)" haben muss (was als Einstiegspunkt genutzt wird).

    Das Programm des Threaderstellers funktioniert ja auch nicht! Denn es hat keine gültige main-Funktion! Aber der Compiler muss ein int main; schlucken, denn er kann ja nicht wissen, was ich später damit anstelle. Vielleicht will ich ja kein lauffähiges Programm. Vielleicht will ich das später als Variable in einer freestanding-Implementierung benutzen. Vielleicht will ich das hinterher mit einem wilden Fortran-Code linken, indem die Startfunktion ganz anders heißt. Vielleicht will ich einen Editor für Objektdateien testen. Wenn ich int main; schreibe, dann soll mir einfach nur eine Objektdatei erstellt werden, in der ein Symbol namens main existiert, das Speicherplatz für einen Integer ist. Was ich mit dem Symbol später anstelle, das hat den Compiler erst einmal gar nichts anzugehen. main ist für den Compiler nichts besonderes*, interessant wird es erst, wenn ein fertiges Programm erstellt wird. Dann sollte die main eine Funktion mit passender Signatur sein.

    Bloß wenn ich hinterher versuche, diese Variable wie eine main-Funktion zu linken, dann darf ich nicht erwarten (außer ich habe ganz schlaue Tricks angestellt), dass ein gültiges Programm rauskommt.

    Sind diese schlauen Tricks mit dem Standard verträglich?

    Bestimmt nicht. Ich weiß nicht mal, ob so etwas möglich ist, Jedenfalls ist es vorstellbar.

    *: Außer der Sonderregelung, dass in einer Funktion namens main ein return 0 implizit ist.



  • Danke SeppJ.



  • wow einer der sich bedankt. welch seltenheit in diesem forum. 😃



  • Also zusammengefasst:

    a) int main; sollte vom Compiler geschluckt werden, weil es direkt beim Übersetzen erstmal keiner Regel widerspricht.
    b) Beim Linken eines konformen C++-Programms auf einem "hosted environment" muss es dann zu einem Fehler kommen, weil der Standard verlangt, dass erstens eine Funktion int main(/*params*/) in irgendeiner ÜE vorhanden sein muss und zweitens das Symbol dieser Funktion mit dem Symbol der Variablen aus der anderen ÜE kollidiert.

    - Wenn der Linker sich nicht beschwert, weil er entweder eine andere Funktion als Einstiegspunkt akzeptiert (z.B. _tWinMain) oder aber durch irgendwelche obskure magie aus int main; eine Funktion erkennt (wie beim TE offenbar der Fall), dann ist das eine Erweiterung des jeweiligen Linkers, die nicht mehr Standardkonform ist.
    - Zeus' Code ist damit nicht ill-formed, das resultieren Programm dagegen schon. Dass es funktioniert, liegt an der Erweiterung des MSVC.
    - Ebenso ist das Programm des Threaderstellers im Sinne des Standars ill-formed. Dass der Linker keine Zähne spuckt, liegt vermutlich an einer entsprechenden Erweiterung. Dass das Programm dann abstürzt liegt daran, dass die Erweiterung nicht gemäß ihren Spezifikationen genutzt wurde (wie auch immer die aussehen mögen)
    - Wenn ich die ÜEs nicht von einem C++-Linker verwursten lasse (SeppJ's hypotetisches Fortran-Beispiel), zieht Punkt b) eh nicht und es darf alles geschehen.

    Richtig?



  • Auch beim MSVC ist main() der Einstiegspunkt, nur daß diese Funktion eben schon in den Runtime-Libs implementiert ist (und diese wird dazugelinkt sobald man entsprechende Optionen (/SUBSYSTEM) beim Linker einstellt):

    int main(/*Parameter*/)
    {
       // code
    
       return WinMain(/*Parameter*/);
    }
    

    Und nur aus User-Sicht ist also WinMain() der Einstiegspunkt.



  • Wo soll es denn ein Problem geben? 😕 Wenn es mit Namen von Variablen Konflikte mit dem Compiler oder Linker gibt, wählt man einfach andere! 🤡


  • Administrator

    Th69 schrieb:

    Auch beim MSVC ist main() der Einstiegspunkt, nur daß diese Funktion eben schon in den Runtime-Libs implementiert ist (und diese wird dazugelinkt sobald man entsprechende Optionen (/SUBSYSTEM) beim Linker einstellt):

    int main(/*Parameter*/)
    {
       // code
    
       return WinMain(/*Parameter*/);
    }
    

    Und nur aus User-Sicht ist also WinMain() der Einstiegspunkt.

    Das ist so nicht korrekt.
    Bei /SUBSYSTEM:CONSOLE ist es mainCRTStartup oder wmainCRTStartup .
    Bei /SUBSYSTEM:WINDOWS ist es WinMainCRTStartup oder wWinMainCRTStartup .
    Bei einer DLL ist es _DllMainCRTStartup .

    Es heisst schliesslich nirgends, dass main der absolute Einstiegspunkt sein muss. Es ist nur der Einstiegspunkt in deinen Code.

    Kannst du auch hier nachlesen:
    http://msdn.microsoft.com/en-us/library/f9t8842e.aspx

    Man sollte zudem vielleicht auch die ganzen Paragraphen von vorhin zitieren:

    ISO 14882:2003 3.6.1 Main function Abschnitt 1 schrieb:

    A program shall contain a global function called main, which is the designated start of the program. It is implementation-defined whether a program in a freestanding environment is required to define a main function. [Note: in a freestanding environment, start-up and termination is implementation-defined; start-up contains the execution of constructors for objects of namespace scope with static storage duration; termination contains the execution of destructors for objects with static storage duration. ]

    ISO 14882:2003 3.6.1 Main function Abschnitt 3 schrieb:

    The function main shall not be used (3.2) within a program. The linkage (3.5) of main is implementation-defined. A program that declares main to be inline or static is ill-formed. The name main is not otherwise reserved. [Example: member functions, classes, and enumerations can be called main, as can entities in other namespaces. ]

    Grüssli



  • Th69 schrieb:

    Auch beim MSVC ist main() der Einstiegspunkt, nur daß diese Funktion eben schon in den Runtime-Libs implementiert ist (und diese wird dazugelinkt sobald man entsprechende Optionen (/SUBSYSTEM) beim Linker einstellt):

    int main(/*Parameter*/)
    {
       // code
    
       return WinMain(/*Parameter*/);
    }
    

    Und nur aus User-Sicht ist also WinMain() der Einstiegspunkt.

    Es ist ja genau andersherum - besonders wenn ich Dravere Quelle kurz quer lesen - aber trotzdem schreit, wenn ich im irrtum bin 😛

    int RTmain(...) { // Laufzeit-Entry-Point
       return CPPmain(...); // Coded Main-Funktion
    }
    


  • Ja, sorry, ich habe mich vertan.



  • Tja, wer hätte gedacht, dass man da so viel drüber diskutieren kann.
    Also danke Leute, war echt interesssant. Man lernt ja irgendwie nie aus..



  • Globale Variablen/Konstruktoren werden initialisiert bevor main ausgefuehrt wird. Der Destruktor wird nach dem Beenden von main aufgerufen. So gesehen kann main gar nicht der Einstiegspunkt des Programmes sein.


Anmelden zum Antworten