Mombu the Programming Forum sponsored links

Go Back   Mombu the Programming Forum > Programming > Linker, initialization of global variables and the size of INIT segment
User Name
Password
REGISTER NOW! Mark Forums Read

sponsored links


Reply
 
1 10th December 12:44
nox metus
External User
 
Posts: 1
Default Linker, initialization of global variables and the size of INIT segment


Hello.

Whenever you are writing a big project using Borland C++ Builder (no matter
which version) one day you will face the situation when some of global
variables constructors have never been called.

I met various discussions on this issue. TeamB usually replies that the
problem is in the undefined order of initialization of modules. This is
obviously not true since in accordance with do***entation order of
initialization is defined by linkage order or by dependency order if
"#pragma package" is used.

Let me present my own investigation of this issue.

Well, how runtime deals with initialization? This is very simple: compiler
defines _INIT_ segment in each object file. Entry for each module consists
from 2 values: the address of init procedure and priority. Then linker
generates initialization procedure for each module and puts the address of
the generated to the entry in _INIT_ segment. The signature of linker
generated procedure is __linkproc__ MODULENAME::Initialize(). Generally this
function body is empty. But when being initialized module has global
variables Initialize() function makes call to _STCON0_() function which at
last constructs global objects.

During start up runtime simply cycles through _INIT_ segment and calls init
procedures first in order of priorities, then in order of entries in _INIT_
segment. MODULENAME::Initialize() generally has priority equal to 30.

I have ****yzed _INIT_ segment in rather big project where I faced with the
problem. I found that for all modules correct __linkproc__
MODULENAME::Initialize() procedures and corresponding _STCON0_() were
generated. But _INIT_ segment contained those procedures only for the first
96 modules in the project. Other modules were simply omitted from the _INIT_
segment. And, of course, for omitted modules global objects were never been
constructed. DAMN!!!

So I can conclude that this problem arises from just another serious bug in
ilink32.exe which for some reasons restricts the size of _INIT_ segment.

Now I have question to TeamB. Why despite the bug is a several years old it
is not fixed at the moment? When it is going to be fixed?

There is another "famous" bug in ilink32 with many years history. Namely,
ilink32 does not link object files bigger than 4Mb. This bug also seems
never going to be fixed, despite so many people point it. Why?

Nox Metus.
  Reply With Quote


  sponsored links


2 10th December 12:44
maeder
External User
 
Posts: 1
Default Linker, initialization of global variables and the size of INITsegment


"Nox Metus" <noxmetus@pisem.net> writes:

Only if you use global variables of class type.


I can't remember somebody arguing that the reason for a global object *never*
to be constructed was the undefined order of initialization (without being
corrected, anyway).

That order can certainly cause an object not yet to be constructed at a
certain point during the execution of the program; but I don't think that it
can prevent an object from being constructed at all.


Could you please indicate which part of the do***entation you write about?
I don't doubt what you write, but discussing is easier if both sides discuss
the same text.


This looks like the start of a reproducible test case. Does that number 96
depend on the size of the modules, or can you demonstrate this behavior
by any project of >96 modules, even if each just defines a global object of
class type?

When you write "global object", do you mean "global" as in "global namespace",
or as in "defined in namespace scope"? I.e. does the problem also occur if
you have

// Object.h
class Object
{
public:
Object();

int id() const;

private:
int myId;
};

//Object.cpp
#include "Object.h"

namespace
{
int count(0);
}

Object::Object()
: myId(count++)
{
}

int Obect::id() const
{
return myId;
}


, a sufficient number of modules like this:

#include "Object.h"

namespace
{
Object const o;
}

int f37()
{
return o.id();
}


, and a main() function calling all these fnn()s?

The reason I'm asking this is that this test case does certainly not depend
on module initialization order.


I've just created these sources (http://www.glue.ch/~maeder/linker-issue.zip)
and built them with both gcc 3.3.2 (g++ main.cpp module*.cpp Object.cpp)
and C++BuilderX (bcc32 main.cpp module*.cpp Object.cpp). Both executables
correctly printed the numbers 0 to 98 (in varying order). What do you get
with the C++ Builder version you are using?

Could be.


[These newsgroups are peer support groups for all Borland users. TeamB members
are just a tiny fraction of all these participants; why do you exclude
everybody else?]

There may be several reasons:
- nobody may have done an ****ysis as thorough as what you have done
- nobody was able to come up with a reproducible test case
- a reproducible test case was submitted to Borland but they chose not to
fix the problem, because
* they didn't understand the problem
* the bug can was considered less important than other work because it
can easily be worked around by not defining global objects of class type
* they decided to invest their resources on different things
* ...
- ...

Again, please don't think that the fact that this reply comes from a TeamB
member causes it to be more valuable than a reply from somebody who isn't.
I'm just speculating and applying (what I think is) common sense. There's
no reason to assume that I'm better at this than anybody else.

Please also note that I don't think it's ok for Borland not to fix certain
bugs. I'm just establishing a speculative list of reasons.


See above.
  Reply With Quote
3 10th December 12:44
nox metus
External User
 
Posts: 1
Default Linker, initialization of global variables and the size of INIT segment


Hello, Thomas!
Thank you for answer.
Please, see my comments below.

"Thomas Maeder [TeamB]" <maeder@glue.ch> writes:

NM>> Whenever you are writing a big project using Borland C++ Builder (no
matter
NM>> which version) one day you will face the situation when some of global
NM>> variables constructors have never been called.

TM> Only if you use global variables of class type.
Yes, of course. What else type of variable needs constructor to be called?

NM>> I met various discussions on this issue. TeamB usually replies that the
NM>> problem is in the undefined order of initialization of modules. This is
NM>> obviously not true

TM> I can't remember somebody arguing that the reason for a global object
*never*
TM> to be constructed was the undefined order of initialization (without
being
TM> corrected, anyway).
Yes, you are right. Order of initialization can not be the reason. And
discussions that I've searched through never suggested this as the reason
for constructors never been called they only doubted that author of the
topic check construction in right way. You may find such discussions by
typing something like "global variables initialization borland". For
instance this is first that comes to my sight:
http://groups.google.com.ru/groups?q=global+variables+initialization+borland
&hl=ru&lr=&ie=UTF-8&oe=UTF-8&selm=3cebee5d%241_2%40dnews&rnum=5

TM> That order can certainly cause an object not yet to be constructed at a
TM> certain point during the execution of the program; but I don't think
that it
TM> can prevent an object from being constructed at all.
Yes, again, you are perfectly right.

NM>> since in accordance with do***entation order of
NM>> initialization is defined by linkage order or by dependency order if
NM>> "#pragma package" is used.

TM> Could you please indicate which part of the do***entation you write
about?
TM> I don't doubt what you write, but discussing is easier if both sides
discuss
TM> the same text.
Yes, of course. See Borland C++ Builder Help (version 5.0 or 6.0 - it doesn'
t matter) sections "Initialization order of OBJs" and "Initialization order
of units". Also I checked it by ****yzing RTL source code (see procedure
_init_exit_proc in initexit.c).


TM> This looks like the start of a reproducible test case. Does that number
96
TM> depend on the size of the modules, or can you demonstrate this behavior
TM> by any project of >96 modules, even if each just defines a global object
of
TM> class type?
Well, at that moment I can't introduce such test case. In fact I was too
angry when write the topic since I lost vast of time trying to understand
what's going wrong. The project that I worked on works well on several
platforms with many different compilers (gcc, msvc for example) and I was
really surprised by amount of workarounds that I had to implement to simply
compile it by BCB. I think that in a day or two I will prepare test project
that reproduces the issue and publish it.

TM> When you write "global object", do you mean "global" as in "global
namespace",
TM> or as in "defined in namespace scope"? I.e. does the problem also occur
if
TM> you have
Both the classes and instantiated objects were defined in certain namespace
(not global).

TM> I've just created these sources
(http://www.glue.ch/~maeder/linker-issue.zip)
TM> and built them with both gcc 3.3.2 (g++ main.cpp module*.cpp Object.cpp)
TM> and C++BuilderX (bcc32 main.cpp module*.cpp Object.cpp). Both
executables
TM> correctly printed the numbers 0 to 98 (in varying order). What do you
get
TM> with the C++ Builder version you are using?
I have BCB 5.0. Your example works perfectly. Now I work on reproducible
example.

TM> Again, please don't think that the fact that this reply comes from a
TeamB
TM> member causes it to be more valuable than a reply from somebody who
isn't.
TM> I'm just speculating and applying (what I think is) common sense.
There's
TM> no reason to assume that I'm better at this than anybody else.
TM>
TM> Please also note that I don't think it's ok for Borland not to fix
certain
TM> bugs. I'm just establishing a speculative list of reasons.
Ok, I understand.
  Reply With Quote
4 10th December 12:44
maeder
External User
 
Posts: 1
Default Linker, initialization of global variables and the size of INITsegment


"Nox Metus" <noxmetus@pisem.net> writes:

Automatic objects, objects with dynamic lifetime, temporary objects,
static local objects.


I've found the section in bcb6lang.hlp. It pretty much matches what you
  Reply With Quote
Reply


Thread Tools
Display Modes




Copyright 2006 SmartyDevil.com - Dies Mies Jeschet Boenedoesef Douvema Enitemaus -
666