namespaces and main()

P

poiuz24

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?
 
V

Victor Bazarov

poiuz24 said:
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
 
J

JKop

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
 
M

Mike Wahler

JKop said:
poiuz24 posted:



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
 
M

Mark A. Gibbs

JKop said:
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
 
O

Owen Jacobson

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
 
P

poiuz24

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 ::

???
 
P

poiuz24

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 ::

???
 
J

John Harrison

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
 
P

poiuz24

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?
 
P

poiuz24

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;
"""
 
K

Karl Heinz Buchegger

poiuz24 said:
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.
 
T

tom_usenet

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
 
V

Victor Bazarov

poiuz24 said:
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
 
J

JKop

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
 
P

poiuz24

tom_usenet said:
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 ..
 
P

poiuz24

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
 
T

tom_usenet

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
 
T

tom_usenet

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
 
K

Karl Heinz Buchegger

poiuz24 said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top