int main;



  • SeppJ schrieb:

    Du darfst andere mains definieren wie du lustig bist. Leute, könnt ihr alle nicht mehr zwischen Compiler und Linker unterscheiden? 😮

    Sorry ich schreib mein Compiler in Java 😮 😃



  • SeppJ schrieb:

    Leute, könnt ihr alle nicht mehr zwischen Compiler und Linker unterscheiden? 😮

    Wenn ich Programm schreibe, dann meine ich das, was der C++-Standard darunter versteht (keine Ahnung, wie du plötzlich auf Compiler kommst):

    C++ Standard schrieb:

    A program consists of one or more translation units (Clause 2) linked together.

    Wenn im Ursprungspost von "das Programm startet und stürzt ab" die Rede ist, dann ist das wohl die einzig sinnvolle Interpretation.

    Mods, könnt ihr alle nicht mehr zwischen Programm und Übersetzungseinheit unterscheiden?

    C++ Standard schrieb:

    If there is more than one [..] matching entity, the program is ill-formed.

    Wenn jemand eine globale Variable int main; definiert, dann ist das Programm(!) ill-formed, da es entweder (a) mehrere Symbole "main" enthält oder (b) keine Funktion "main" besitzt.

    Was du vorher schriebst, dürfte damit widerlegt sein.

    SeppJ schrieb:

    Es heißt nur, dass du, wenn du eine main Funktion mit den genannten Parametern hast, dann kann man daraus ein gültiges Programm erstellen. Du darfst andere mains definieren wie du lustig bist.



  • @idontgotit
    Du schießt fast immer daneben, aber mit ill-formed hast ein bisschen getroffen.

    // a non-ill-formed program
    int main;
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {....}
    

    Deswegen sind die Satze bezüglich den Namen main eigentlich auch nur Empfehlungen/Ratschläge/Verpflichtungen, aber keine harte Einschräkung/Gesetzt/Regeln. Daraus folgt, dass ein Compiler auch nicht harte Fehler melden muss.


  • Mod

    idontgotit schrieb:

    SeppJ schrieb:

    Leute, könnt ihr alle nicht mehr zwischen Compiler und Linker unterscheiden? 😮

    Wenn ich Programm schreibe, dann meine ich das, was der C++-Standard darunter versteht (keine Ahnung, wie du plötzlich auf Compiler kommst):

    Weil das das Problem ist! Du darfst mains definieren wie du lustig bist. Bloß wenn du anfängst, die falschen mains zu einem Programm zusammenzulinken, dann ist dir nicht mehr garantiert, dass ein lauffähiges Programm rauskommt. Es darf aber selbstverständlich ein lauffähiges Programm rauskommen, das Definieren anderer mains ist nicht verboten und es ist mir immer noch nicht klar, wo du dieses Verbot siehst. Der Standard erwähnt sogar explizit, dass andere Arten ein gültiges Programm zu erhalten erlaubt sind (im Teil über Startup and Termination und über hosted und freestanding evironments [aus dem Gedächtnis zitiert]).



  • SeppJ schrieb:

    Es darf aber selbstverständlich ein lauffähiges Programm rauskommen, das Definieren anderer mains ist nicht verboten und es ist mir immer noch nicht klar, wo du dieses Verbot siehst.

    Das Definieren an sich ist nicht an sich verboten, nur kann man damit später nie ein gültiges Programm erstellen. Das habe ich so deutlich geschrieben.

    SeppJ schrieb:

    Der Standard erwähnt sogar explizit, dass andere Arten ein gültiges Programm zu erhalten erlaubt sind (im Teil über Startup and Termination und über hosted und freestanding evironments [aus dem Gedächtnis zitiert]).

    Es steht nur, dass die freestanding environments auf main verzichten dürfen, ist es hosted (wovon wohl die Rede ist), ist eine globale Funktion main, die als Einstiegspunkt genutzt wird, Pflicht.

    Zeus schrieb:

    // a non-ill-formed program
    int main;
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {....}
    

    Was soll daran legal sein? Nur weil es der (sowieso nicht standardgetreue) MSVC akzeptiert, heisst das noch lange nicht, dass es nicht ill-formed wäre.



  • idontgotit schrieb:

    Zeus schrieb:

    // a non-ill-formed program
    int main;
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {....}
    

    Was soll daran legal sein? Nur weil es der (sowieso nicht standardgetreue) MSVC akzeptiert, heisst das noch lange nicht, dass es nicht ill-formed wäre.

    Willst du nur trollen, soll ich jetzt deine eigene Kommentare zitieren, warum das Programm nicht ill-formed ist?

    If there is more than one [..] matching entity, the program is ill-formed.

    Ein Win32-API-Programm hat keine Main Funktion als Einstiegspunkt. Daher gibst auch durch die Deklaration von int main auch nur eine Entity.



  • Zeus schrieb:

    Willst du nur trollen

    Nichts liegt mir ferner.

    Zeus schrieb:

    Ein Win32-API-Programm hat keine Main Funktion als Einstiegspunkt.

    Die muss es aber haben, sonst ist es kein C++.

    C++ Standard 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.

    Für dein Beispiel wichtig: "designated start of the program"
    Für SeppJ wichtig: "It is implementation-defined [...] in a freestanding environment".


  • Mod

    Ist dir der Unterschied nicht klar, zwischen müssen und dürfen? Ja, ein Programm ohne int main() oder int main(int char**) muss nicht funktionieren. Es darf aber funktionieren, wenn es andere mains gibt! Möchtest du denn verbieten, dass ich in meinem freestanding environment eine globale Variable namens main definiere? Das muss der Compiler fressen. 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. Tut es ja auch nicht! Darum darf ich trotzdem eine Variable haben, die so heißt. Was ist daran so schwer zu kapieren?

    Da ich das inzwischen dreimal geschrieben habe und als Antwort immer Stellen aus dem Standard vorgesetzt bekommen haben, die mich bestätigen, sehe ich keine Grund noch ein viertes Mal diese Antwort zu geben, wenn nichts neues kommt.



  • SeppJ schrieb:

    Da ich das inzwischen dreimal geschrieben habe und als Antwort immer Stellen aus dem Standard vorgesetzt bekommen haben, die mich bestätigen, sehe ich keine Grund noch ein viertes Mal diese Antwort zu geben, wenn nichts neues kommt.

    Gut, sehe es so, dass ich es nicht schaffe, den Standard richtig zu interpretieren und du mir zeigst, wie es geht. Kapiert habe ich ihn immer noch nicht.

    Möchtest du denn verbieten, dass ich in meinem freestanding environment eine globale Variable namens main definiere?

    Bitte lass das freestanding environment weg, da ist alles vieles erlaubt und es kommt selten vor. (Btw: Wenn eine Win32-Anwendung als freestanding gilt, hat Zeus natürlich recht)

    In meinen Augen steht

    Ja, ein Programm ohne int main() oder int main(int char**) muss nicht funktionieren

    (in hosted environments) in direkten Gegensatz zu

    A program shall contain a global function called main, which is the designated start of the program.

    da jedes (gehostete) Programm eine Funktion haben muss (== "shall" und "shall" != "darf"), die "main" heisst und "int" zurückgibt.

    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).

    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?


  • 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