Order of cpp files matters?

P

pooh

I have a situation where the order of my cpp files in my g++ compile
command line affects the program.

Here is a simplified example:

g++ -Wall -o test a.cpp b.cpp

compiles, links and runs fine.

g++ -Wall -o test b.cpp a.cpp

compiles, and links fine (no errors or warnings) but returns a
segmentation fault when run.

I did not think that the order of the files mattered.
g++ (GCC) 3.3.4 on Debian Linux 2.4.26-1-386
 
M

Mike Wahler

pooh said:
I have a situation where the order of my cpp files in my g++ compile
command line affects the program.

Here is a simplified example:

g++ -Wall -o test a.cpp b.cpp

compiles, links and runs fine.

g++ -Wall -o test b.cpp a.cpp

compiles, and links fine (no errors or warnings) but returns a
segmentation fault when run.

We have no way of discerning the problem without seeing
the code. Some possibilites (these are only guesses)
are:

Somewhere your code is producing undefined behavior
(symptoms of which can include 'seems to work'), which
is being manifested differently with different 'build
orders'.

Perhaps you have global objects in different translation
units which depend upon a certain order of creation
(this order is not specified by the language).

But again, nobody can know for sure without seeing the
code.

I did not think that the order of the files mattered.

It can.

-Mike
 
T

Thomas Matthews

pooh said:
I have a situation where the order of my cpp files in my g++ compile
command line affects the program.

Here is a simplified example:

g++ -Wall -o test a.cpp b.cpp

compiles, links and runs fine.

g++ -Wall -o test b.cpp a.cpp

compiles, and links fine (no errors or warnings) but returns a
segmentation fault when run.

I did not think that the order of the files mattered.
g++ (GCC) 3.3.4 on Debian Linux 2.4.26-1-386

When linking, some linkers only perform a single pass.
This may have something to do with external dependencies,
things referenced outside of a given translation unit.

In some linkers, the object files have to be listed more
than once in order to satisfy undefined symbols.

Try this:
g++ -Wall -c -o a.o a.cpp
g++ -Wall -c -o b.o b.cpp
g++ -o test a.o b.o

also try this:
g++ -o test b.o a.o


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 
P

pooh

Thomas said:
When linking, some linkers only perform a single pass.
This may have something to do with external dependencies,
things referenced outside of a given translation unit.

In some linkers, the object files have to be listed more
than once in order to satisfy undefined symbols.

Try this:
g++ -Wall -c -o a.o a.cpp
g++ -Wall -c -o b.o b.cpp
g++ -o test a.o b.o

also try this:
g++ -o test b.o a.o
I think found the cause of the problem but I'm uncertain as to the reason.

(Sorry but I'm new to c++ so my terminology below may not be quite accurate)

In one of my class headers (.h file) I have an extern statement to allow
the class to be initialized globally.

(in my A.h file):
class A
{ <snip> }

extern A gclA;

I initialize a global object using this class at the end of the
corresponding cpp file.

(in my A.cpp file):
<snip>
A gclA();

But if I switch the g++ command line order of A.cpp with one that is
dependent on it (B.cpp) the program compiles and links but generates a
segmentation fault when run. The opposite order works fine.

Today I found that if I move the initialization of the global object
from A.cpp to main.cpp (which contains the main() function) then the
order of A.cpp and B.cpp no longer causes a problem.

I guess the logic is simply that the program linking somehow determines
when my global object gets initialized and if I get the order wrong the
dependent code fails? Seems odd to me but then again, I think global
variables should be avoided (and this is maybe one of the many reasons
why?).

I'm tempted to pass all "globals" as parameters. Is this practical?

What is a "translation unit". That term is new to me (as is c++).

Thanks
 
S

shez

pooh said:
I guess the logic is simply that the program linking somehow determines
when my global object gets initialized and if I get the order wrong the
dependent code fails? Seems odd to me but then again, I think global
variables should be avoided (and this is maybe one of the many reasons
why?).

Pooh,

Try not to use global variables in your program. If you absolutely
must access something globally, you can use the singleton pattern:

YourClass& getMySingleton()
{
static YourClass object;
return object;
}

Now you access your object through this function call, e.g.:

getMySingleton().doSomething(...);

This pattern ensures that your object is always fully constructed
before it is used.

I'm tempted to pass all "globals" as parameters. Is this practical?

Not if you use the singleton pattern (see above).
What is a "translation unit". That term is new to me (as is c++).

Thanks

To put it simply, the translation unit is what your compiler sees after
all your header files have been included. The compiler treats the
whole thing as a single "file" and will generate object code (.o file)
for it. Then the object code for all translation units will be linked
to produce your executable file.

-shez-
 
K

Karl Heinz Buchegger

pooh said:
[snip]
In one of my class headers (.h file) I have an extern statement to allow
the class to be initialized globally.

(in my A.h file):
class A
{ <snip> }

extern A gclA;

I initialize a global object using this class at the end of the
corresponding cpp file.

(in my A.cpp file):
<snip>
A gclA();

Note: The above does not define the global object, but it
declares a function called gclA, which takes no parameters and
returnes an A object. You ment

A gclA;
But if I switch the g++ command line order of A.cpp with one that is
dependent on it (B.cpp) the program compiles and links but generates a
segmentation fault when run. The opposite order works fine.

Today I found that if I move the initialization of the global object
from A.cpp to main.cpp (which contains the main() function) then the
order of A.cpp and B.cpp no longer causes a problem.

All of this points to one possible conclusion:
There is something else wrong in your program.
It might be that you have an array overflow somewhere in your program
or you access memory with an invalid pointer or things like that.

The reason is:
Linking in different order or moving variables around don't alter
the logical structure of your program but they do alter the specific
memory layout of your program (where in memory are what things
located). You now have found that in specific memory layouts
your program crashes while in others it doesn't. The key to this
is: Usually things are not put in sequence in memory but the compiler
(or linker) inserts some padding bytes between them. In some of
these memory layouts your 'bug' cannot be seen, because you simply
alter some of those padding bytes und thus do no harm to the real
program or variables, while in other configurations
you overwrite vital program information which happens just to be
at those 'hot' areas, because of the specific memory layout.
I guess the logic is simply that the program linking somehow determines
when my global object gets initialized and if I get the order wrong the
dependent code fails?

Could also be:
If you have multiple global objects and their initialization
order is dependent on each other. Avoid such cases if possible.
You can easiliy detect things like that by putting breakpoints
on all constructors of all the global variables and see in
which order they get called.
Seems odd to me but then again, I think global
variables should be avoided (and this is maybe one of the many reasons
why?).

I'm tempted to pass all "globals" as parameters. Is this practical?

What is a "translation unit". That term is new to me (as is c++).

It is one unit that is fed to the compiler independent of all
other units. Usually it is a single cpp source code 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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top