namespaces and main()

Discussion in 'C++' started by poiuz24, Jul 21, 2004.

  1. poiuz24

    poiuz24 Guest

    aeh, this may be stupid, but could s.b. please explain
    to me why the following won't link (gcc 3.3)?

    foo.cpp = """
    namespace foo
    {
    int main ()
    {
    return 0;
    }
    }

    using namespace foo;
    """

    it fails with symbol "_main" undefined. it doesn't link either
    when i wrap up the using statement like so:

    extern "C" {
    using namespace foo;
    }

    what's the problem?
     
    poiuz24, Jul 21, 2004
    #1
    1. Advertising

  2. poiuz24 wrote:
    > aeh, this may be stupid, but could s.b. please explain
    > to me why the following won't link (gcc 3.3)?
    >
    > foo.cpp = """
    > namespace foo
    > {
    > int main ()
    > {
    > return 0;
    > }
    > }
    >
    > using namespace foo;
    > """
    >
    > it fails with symbol "_main" undefined. it doesn't link either
    > when i wrap up the using statement like so:
    >
    > extern "C" {
    > using namespace foo;
    > }
    >
    > what's the problem?


    Each program shall contain a _global_ 'main' function. Your function
    is not global, it's inside a namespace. "using" is for your code, not
    the library code. When you say "using namespace foo", you do not cause
    recompilation of the library code that would suddenly resolve your
    "::foo::main" by just using unqualified name "main".

    IOW, the code is not a complete C++ program because it's missing the
    global function 'main', which is required. That's why it won't link.

    Victor
     
    Victor Bazarov, Jul 21, 2004
    #2
    1. Advertising

  3. poiuz24

    JKop Guest

    poiuz24 posted:

    > aeh, this may be stupid, but could s.b. please explain
    > to me why the following won't link (gcc 3.3)?
    >
    > foo.cpp = """
    > namespace foo
    > {
    > int main ()
    > {
    > return 0;
    > }
    > }
    >
    > using namespace foo;
    > """
    >
    > it fails with symbol "_main" undefined. it doesn't link

    either
    > when i wrap up the using statement like so:
    >
    > extern "C" {
    > using namespace foo;
    > }
    >
    > what's the problem?



    You're correct in thinking that:

    int foo::main();

    becomes:

    int ::main();


    after the line

    using namespace foo;


    The only problem is that this only applies to the current
    translation unit. So when the linker is introduced to the
    function, it's name is:

    int foo::main();

    when what it wants is:

    int ::main();


    PS Why the hell does it say "_main" is undefined? Why the
    underscore?


    -JKop
     
    JKop, Jul 21, 2004
    #3
  4. poiuz24

    Mike Wahler Guest

    "JKop" <> wrote in message
    news:xmzLc.5157$...
    > poiuz24 posted:
    >
    > > aeh, this may be stupid, but could s.b. please explain
    > > to me why the following won't link (gcc 3.3)?
    > >
    > > foo.cpp = """
    > > namespace foo
    > > {
    > > int main ()
    > > {
    > > return 0;
    > > }
    > > }
    > >
    > > using namespace foo;
    > > """
    > >
    > > it fails with symbol "_main" undefined. it doesn't link

    > either
    > > when i wrap up the using statement like so:
    > >
    > > extern "C" {
    > > using namespace foo;
    > > }
    > >
    > > what's the problem?

    >
    >
    > You're correct in thinking that:
    >
    > int foo::main();
    >
    > becomes:
    >
    > int ::main();
    >
    >
    > after the line
    >
    > using namespace foo;
    >
    >
    > The only problem is that this only applies to the current
    > translation unit. So when the linker is introduced to the
    > function, it's name is:
    >
    > int foo::main();
    >
    > when what it wants is:
    >
    > int ::main();
    >
    >
    > PS Why the hell does it say "_main" is undefined? Why the
    > underscore?


    Many implementations 'decorate' identifiers before creating
    the translated output. Prepending an undescore is a fairly
    common practice.

    -Mike

    >
    >
    > -JKop
     
    Mike Wahler, Jul 22, 2004
    #4
  5. JKop wrote:
    > PS Why the hell does it say "_main" is undefined? Why the
    > underscore?


    in c++, the compiler mangles function names in a compiler-specific way
    by default (in my case, foo::main became ?main@foo@@YAHXZ). in "c"
    linkage (extern "c" in a c++ program, default in a c program), the only
    mangling is to prepend an underscore onto the function name. ::main()
    uses c linkage.

    indi
     
    Mark A. Gibbs, Jul 22, 2004
    #5
  6. On Wed, 21 Jul 2004 13:09:56 -0400, Victor Bazarov wrote:

    > poiuz24 wrote:
    >> aeh, this may be stupid, but could s.b. please explain
    >> to me why the following won't link (gcc 3.3)?
    >>
    >> foo.cpp = """
    >> namespace foo
    >> {
    >> int main ()
    >> {
    >> return 0;
    >> }
    >> }
    >>
    >> using namespace foo;
    >> """
    >>
    >> it fails with symbol "_main" undefined.

    >
    > Each program shall contain a _global_ 'main' function. Your function
    > is not global, it's inside a namespace. "using" is for your code, not
    > the library code. When you say "using namespace foo", you do not cause
    > recompilation of the library code that would suddenly resolve your
    > "::foo::main" by just using unqualified name "main".
    >
    > IOW, the code is not a complete C++ program because it's missing the
    > global function 'main', which is required. That's why it won't link.


    What I am about to write is probably undefined behaviour. To the OP:
    DON'T DO THIS.

    g++ -W -Wall -ansi -pedantic accepts the following without complaint:
    --- g++-test.cpp
    #include <iostream>
    using std::cout;
    using std::endl;

    namespace foo {
    extern "C"
    int main () {
    cout << "Main!" << endl;
    }
    }
    ---
    $ g++ -W -Wall -ansi -pedantic g++-test.cpp -o g++-test
    $ ./g++-test
    Main!

    Is this, in fact, undefined behaviour? The program entry point is defined
    in terms of the function declaration, not linker names, right? I'm not
    losing my mind, right?

    Owen

    --
    Some say the Wired doesn't have political borders like the real world,
    but there are far too many nonsense-spouting anarchists or idiots who
    think that pranks are a revolution.
     
    Owen Jacobson, Jul 22, 2004
    #6
  7. poiuz24

    poiuz24 Guest

    > Each program shall contain a _global_ 'main' function. Your function
    > is not global, it's inside a namespace. "using" is for your code, not
    > the library code. When you say "using namespace foo", you do not cause
    > recompilation of the library code that would suddenly resolve your


    but i don't have no library: above is all in _one_ file. thus, the
    program == one translation unit == one file

    i thought the using stmt would introduce ::foo::main into ::
    since the using stmt is in ::

    ???
     
    poiuz24, Jul 22, 2004
    #7
  8. poiuz24

    poiuz24 Guest

    > Each program shall contain a _global_ 'main' function. Your function
    > is not global, it's inside a namespace. "using" is for your code, not
    > the library code. When you say "using namespace foo", you do not cause
    > recompilation of the library code that would suddenly resolve your


    but i don't have no library: above is all in _one_ file. thus, the
    program == one translation unit == one file

    i thought the using stmt would introduce ::foo::main into ::
    since the using stmt is in ::

    ???
     
    poiuz24, Jul 22, 2004
    #8
  9. On 21 Jul 2004 23:26:46 -0700, poiuz24 <> wrote:

    >> Each program shall contain a _global_ 'main' function. Your function
    >> is not global, it's inside a namespace. "using" is for your code, not
    >> the library code. When you say "using namespace foo", you do not cause
    >> recompilation of the library code that would suddenly resolve your

    >
    > but i don't have no library: above is all in _one_ file. thus, the
    > program == one translation unit == one file
    >
    > i thought the using stmt would introduce ::foo::main into ::
    > since the using stmt is in ::
    >
    > ???


    By library code Victor means the library code that calls main.

    You must have a function called main in the global namespace.

    A using statement just changes the way names are lookup up, it does not
    means that a name defined in one namespace is now defined in another.

    john
     
    John Harrison, Jul 22, 2004
    #9
  10. poiuz24

    poiuz24 Guest

    > You're correct in thinking that:
    >
    > int foo::main();
    >
    > becomes:
    >
    > int ::main();
    >
    >
    > after the line
    >
    > using namespace foo;
    >
    >
    > The only problem is that this only applies to the current
    > translation unit. So when the linker is introduced to the


    i don't get it: there is only _one_ translation unit
    involved: foo.cpp

    but ok, you say: if foo::main would reside in a different,
    separately compiled translation unit, then the compiler
    would leave the mangled foo::main in say libXXX.o which would
    be different from a mangled ::main. no using stmt could
    change that symbol in libXXX.o from another translation unit.

    so far so good, but even then: in my driving program, i
    introduce foo::main as a synonym for ::main. why is then no
    symbol emitted for ::main in my driving program .o?

    actually, g++ really emits the mangled foo::main :

    -bash-2.05b$ g++ -c foo.cpp
    -bash-2.05b$ nm foo.o
    00000000 t ___gnu_compiled_cplusplus
    00000000 T _f__3fooi
    00000018 T _main__3foov
    00000000 t gcc2_compiled.
    -bash-2.05b$ g++ --version
    2.95.3
    -bash-2.05b$


    tob@blackbox ~/test4
    $ g++ -c foo.cpp

    tob@blackbox ~/test4
    $ nm foo.o
    00000000 b .bss
    00000000 d .data
    00000000 t .text
    00000000 T __ZN3foo4mainEv

    tob@blackbox ~/test4
    $ g++ --version
    g++ (GCC) 3.3.1 (cygming special)
    Copyright (C) 2003 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


    tob@blackbox ~/test4
    $


    btw: i checked if "using foo::main;" would do any better. nope.
    same mangled name.

    this is all strange .. "using" introduces synonyms which are
    fully transparent for the programmer/compiler, but not for
    the linker?
     
    poiuz24, Jul 22, 2004
    #10
  11. poiuz24

    poiuz24 Guest

    got it: one must suppress C++ name mangling at the
    place of definition. this one compiles _and_ links:

    foo.cpp = """
    namespace foo
    {
    extern "C" {
    int main ()
    {
    return 0;
    }
    }
    }

    using namespace foo;
    """
     
    poiuz24, Jul 22, 2004
    #11
  12. poiuz24 wrote:
    >
    > > You're correct in thinking that:
    > >
    > > int foo::main();
    > >
    > > becomes:
    > >
    > > int ::main();
    > >
    > >
    > > after the line
    > >
    > > using namespace foo;
    > >
    > >
    > > The only problem is that this only applies to the current
    > > translation unit. So when the linker is introduced to the

    >
    > i don't get it: there is only _one_ translation unit
    > involved: foo.cpp


    Your program (the source code you wrote) is not the only thing
    that is running when your program starts up.

    main() is just a function which gets called from the startup
    code right after the executable starts. And that startup code
    expects main() to be in the global namespace.

    If you put main() into a namespace, then this startup code
    would need to be recompiled to accomodate for that. But
    this is not going to happen. The startup code is fixed.
    Just if you wonder 'what does this startup code do?'. Well,
    it initiliazes eg. the memory management, setups the standard
    input output streams (stdin, stdout), things like that. In short
    it initializes the environment your program can expect. Only
    after that setup is completed it calles main() in the global
    namespace.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Jul 22, 2004
    #12
  13. poiuz24

    tom_usenet Guest

    On 21 Jul 2004 23:57:55 -0700, (poiuz24) wrote:

    >got it: one must suppress C++ name mangling at the
    >place of definition. this one compiles _and_ links:
    >
    >foo.cpp = """
    >namespace foo
    >{
    > extern "C" {
    > int main ()
    > {
    > return 0;
    > }
    > }
    >}
    >
    >using namespace foo;
    >"""


    You don't need the "using namespace foo" bit. But the code has
    undefined behaviour, since the standard says that the linkage of main
    is implementation defined, so the extern "C" bit might or might not
    work, since it might be expecting a mangled name.

    But why would you want to do this anyway? You're not allowed to call
    main yourself.

    Tom
     
    tom_usenet, Jul 22, 2004
    #13
  14. "poiuz24" <> wrote...
    > > Each program shall contain a _global_ 'main' function. Your function
    > > is not global, it's inside a namespace. "using" is for your code, not
    > > the library code. When you say "using namespace foo", you do not cause
    > > recompilation of the library code that would suddenly resolve your

    >
    > but i don't have no library: above is all in _one_ file. thus, the
    > program == one translation unit == one file
    >
    > i thought the using stmt would introduce ::foo::main into ::
    > since the using stmt is in ::
    >
    > ???


    It does introduce it into the global scope, but only for calls by _your_
    code. _Your_ code does not call 'main' (nor is it allowed to). For the
    rest of the system (whether you call it "library" or not), the function
    is still foo::main.

    I am not sure what your agenda is, but according to the Standard your
    program doesn't have the required _global_ 'main' function. Bringing
    the name 'main' declared inside a namespace into the global scope does
    not make the function global.

    V
     
    Victor Bazarov, Jul 22, 2004
    #14
  15. poiuz24

    JKop Guest

    poiuz24 posted:

    > got it: one must suppress C++ name mangling at the
    > place of definition. this one compiles _and_ links:
    >
    > foo.cpp = """
    > namespace foo
    > {
    > extern "C" {
    > int main ()
    > {
    > return 0;
    > }
    > }
    > }
    >
    > using namespace foo;
    > """


    That's a hack.

    The function's name is:

    int foo::main();

    When using extern "C", it gets introduced to the linker as:

    int main();

    The scope thingie is lost, simply because C-linked functions can't have a
    namespace.

    Anyway, putting main() in a namespace is stupid.


    -JKop
     
    JKop, Jul 22, 2004
    #15
  16. poiuz24

    poiuz24 Guest

    tom_usenet <> wrote in message news:<>...
    > On 21 Jul 2004 23:57:55 -0700, (poiuz24) wrote:
    >
    > >got it: one must suppress C++ name mangling at the
    > >place of definition. this one compiles _and_ links:
    > >
    > >foo.cpp = """
    > >namespace foo
    > >{
    > > extern "C" {
    > > int main ()
    > > {
    > > return 0;
    > > }
    > > }
    > >}
    > >
    > >using namespace foo;
    > >"""

    >
    > You don't need the "using namespace foo" bit. But the code has
    > undefined behaviour, since the standard says that the linkage of main
    > is implementation defined, so the extern "C" bit might or might not


    ah, ok. i silently assumed that ::main would be plainly required to
    have C linkage by the standard. so many implementation defined
    behaviours. whine.

    > work, since it might be expecting a mangled name.
    >
    > But why would you want to do this anyway? You're not allowed to call
    > main yourself.


    logical program structure. I contemplated over having a logical structure
    roughly like this:


    #include <iostream>

    namespace megacorp
    {
    namespace projectx
    {
    namespace modules
    {
    namespace mylib
    {
    void foo () { std::cout << "foo ()" << std::endl; }
    }
    namespace mylib2
    {
    void foo2 () { std::cout << "foo2 ()" << std::endl; }
    }
    }
    namespace apps
    {
    namespace myapp1
    {
    using namespace modules::mylib;
    int main () { foo (); return 0; };
    }
    namespace myapp2
    {
    using namespace modules::mylib2;
    int main () { foo2 (); return 0; };
    }
    }
    }
    }


    to build one of the apps, i'd just do

    #include "stuff"
    using namespace megacorp::projectx::apps::myapp1;

    or

    #include "stuff"
    using namespace megacorp::projectx::apps::myapp2;

    to build the libs, i do:

    #include "stuff"
    using namespace megacorp::projectx::libs::mylib;

    well, ok. I can plainly forward

    #include "stuff"

    int main ()
    {
    return megacorp::projectx::apps:myapp1::main ();
    }


    but for some obscure reasons, I first tried the former version,
    found that it didn't work and then wanted to learn why.
    it's tolarable to have the second version;)

    another background was this: i do lot of templated stuff which
    needs to be included with definitions anyway (when export is not
    there ..). so i thought maybe i can rid of those nasty header
    files altogether. i hate header files. why write code twice? problem
    of course with above example is that namespace scoped non-templated
    functions may only be defined once (the obnoxious "One Definition Rule").

    this one i don't understand either: with namespace scoped templated
    functions, having multiple (of course identical) definitions is
    _separate_ translation units is allowed by the standard as far as
    I know and no problem for the linker to sort out. same goes for const
    vars, structs, classes, typedef, ... but NOT plain functions. why?

    IOW: how do i get rid of headers;)

    sideconditions:
    i dont care a lot on compilation speed .. i don't develop
    million line programs .. i just go buy more Ghz

    i also dont care about "users" seeing ugly definitions instead
    of a "pure" interface in separate headers. users should consult
    the (doxygen generated) docs anyway .. not look at code.

    in java, nobody complaints ..


    >
    > Tom
     
    poiuz24, Jul 22, 2004
    #16
  17. poiuz24

    poiuz24 Guest

    > Your program (the source code you wrote) is not the only thing
    > that is running when your program starts up.


    i suppose at least the OS kernel will run;)
    seriously, that one i was aware of ..

    >
    > main() is just a function which gets called from the startup
    > code right after the executable starts. And that startup code
    > expects main() to be in the global namespace.
    >
    > If you put main() into a namespace, then this startup code


    i drag it into ::

    > would need to be recompiled to accomodate for that. But
    > this is not going to happen. The startup code is fixed.
    > Just if you wonder 'what does this startup code do?'. Well,
    > it initiliazes eg. the memory management, setups the standard
    > input output streams (stdin, stdout), things like that. In short
    > it initializes the environment your program can expect. Only
    > after that setup is completed it calles main() in the global
    > namespace.


    from tom_usenet's posting I learned: the real point seems to be that
    the C++ standard does not specify the linkage conventions for ::main ()

    if i force C linkage for my ::main dragged in from foo::main
    that _might_ work or not. its plainly undefined behaviour;(

    thx for posting anyway
     
    poiuz24, Jul 22, 2004
    #17
  18. poiuz24

    tom_usenet Guest

    On 22 Jul 2004 08:52:25 -0700, (poiuz24) wrote:

    >well, ok. I can plainly forward
    >
    >#include "stuff"
    >
    >int main ()
    >{
    > return megacorp::projectx::apps:myapp1::main ();
    >}


    Yup, that's the best way to do it.

    >but for some obscure reasons, I first tried the former version,
    >found that it didn't work and then wanted to learn why.
    >it's tolarable to have the second version;)
    >
    >another background was this: i do lot of templated stuff which
    >needs to be included with definitions anyway (when export is not
    >there ..). so i thought maybe i can rid of those nasty header
    >files altogether. i hate header files. why write code twice?


    You're not writing code twice, just declarations. The separation is
    quite important in very large projects, since .h files should rarely
    be modified.

    problem
    >of course with above example is that namespace scoped non-templated
    >functions may only be defined once (the obnoxious "One Definition Rule").


    Not true if any of the following is true:
    a) They are defined inside a class body.
    b) They are declared inline.
    c) They are in an anonymous namespace.
    d) They are declared static.

    >this one i don't understand either: with namespace scoped templated
    >functions, having multiple (of course identical) definitions is
    >_separate_ translation units is allowed by the standard as far as
    >I know and no problem for the linker to sort out.


    Actually it's quite a big problem for the linker to sort out - some
    linkers can't do it (including one I have used on QNX - .exes ended up
    containing multiple definitions of template functions, causing
    horrendous bloat). Some compilers have complicated prelinkers that get
    around this problem, by assigning each template instantiation to a
    particular translation unit, but this requires multiple compilation
    passes to find out all the required instantiations. This is what
    Comeau C++ does by default.

    If you have multiple definitions of a function, either the
    compiler/linker has to compile them all, assume they are the same and
    discard all but one, or it has to assign the definition to a single
    translation unit and not compile it in any of the others. You can
    imagine the number of passes that would require!

    One way around the bloat issue is just to have a single compilation
    unit for your whole program! This might suit you.

    > same goes for const
    >vars, structs, classes, typedef, ... but NOT plain functions. why?


    const vars have static linkage, so you haven't got multiple
    definitions, rather each translation unit gets a separate copy. For
    static functions this will obviously lead to major code bloat.

    >IOW: how do i get rid of headers;)


    Well, I suggested some ways above, but none of them are recommended
    since they all lead to bloated executables - the linker knows to merge
    different instantations of template functions, but not normal ones.

    >sideconditions:
    >i dont care a lot on compilation speed .. i don't develop
    >million line programs .. i just go buy more Ghz


    It's not just compilation speed. It's the fact that any change at all
    means you have to recompile absolutely everything.

    >i also dont care about "users" seeing ugly definitions instead
    >of a "pure" interface in separate headers. users should consult
    >the (doxygen generated) docs anyway .. not look at code.


    Yes, I don't strongly disagree with that, but the biggest problem is
    the dependency bottleneck. You will have major problems with circular
    dependencies if you're not careful.

    >in java, nobody complaints ..


    Actually, they do. Look up posts by James Kanze on the subject, for
    one.

    It's best not to fight the language - in Java do what it wants, in C++
    do what it wants.

    Tom
     
    tom_usenet, Jul 22, 2004
    #18
  19. poiuz24

    tom_usenet Guest

    On 22 Jul 2004 09:00:03 -0700, (poiuz24) wrote:

    >from tom_usenet's posting I learned: the real point seems to be that
    >the C++ standard does not specify the linkage conventions for ::main ()
    >
    >if i force C linkage for my ::main dragged in from foo::main
    >that _might_ work or not. its plainly undefined behaviour;(
    >
    >thx for posting anyway


    You still seem to misunderstand what a using declaration does - it
    *doesn't* modify the linkage of the original function in any way. e.g.

    namespace foo
    {
    void f();
    }

    using foo::f;
    //linker still expects foo::f, it's just that code below this point
    //looks up f to be foo::f.

    e.g. putting a using declaration at the end of a .cpp file (as you
    were) has no effect whatsoever.

    Tom
     
    tom_usenet, Jul 22, 2004
    #19
  20. poiuz24 wrote:
    >
    > > Your program (the source code you wrote) is not the only thing
    > > that is running when your program starts up.

    >
    > i suppose at least the OS kernel will run;)
    > seriously, that one i was aware of ..


    I worded it badly.
    What I tried to say is:

    The code in main() is not the first code that gets executed
    when your program starts. It is not that your operating system,
    ehen starting up a program does:
    search for main()
    start execution at main()

    main() is the first function (global objects initialzation
    put aside) that gets executed *that is provided by the programmer*

    The real thing is more like this:

    int start_program()
    {
    get_argument_list_from_command_line();
    set_up_stream_system();
    initialize_memory_manager();
    ...

    return main( argc, argv );
    }

    This code is provided by the system library that is linked
    with your executable. So there really is no other choice then
    having main() in the global namespace. And since this code
    is already precompiled, you cannot use some using directives to
    inject main() from some namespace into the global one. For this
    to take effect, the above startup code would need to be recompiled
    with your using directive in sight. But this is not going to happen.

    >
    > from tom_usenet's posting I learned: the real point seems to be that
    > the C++ standard does not specify the linkage conventions for ::main ()


    The C++ standard doesn't specify *any* linkage conventions.
    Linkage conventions are outside the scope of the C++ standard as
    is the whole process of linkage.

    The real point is: You have to play by the rules. You might get
    away by violating the rules on some systems but don't have a
    guarantee for anything. Your next compiler release might force
    main() to have the usual C++ decorated names in the object file.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Jul 23, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John M
    Replies:
    1
    Views:
    1,243
    Kumar Reddi
    May 29, 2005
  2. Hal Styli
    Replies:
    14
    Views:
    1,686
    Old Wolf
    Jan 20, 2004
  3. Frederick Ding

    int main() or int main(void)?

    Frederick Ding, Dec 3, 2005, in forum: C Programming
    Replies:
    10
    Views:
    667
  4. ravi
    Replies:
    28
    Views:
    998
    Richard Heathfield
    Sep 26, 2007
  5. Jens Peter Hansen
    Replies:
    7
    Views:
    566
    Randy Webb
    Jun 19, 2004
Loading...

Share This Page