Page 1 of 1

C++ construction order

Posted: Wed Apr 29, 2009 6:24 am
by DrLecter
Hi,

Building a hobby OS in C++ I started with your tutotial at http://wiki.osdev.org/C_PlusPlus.
I have 12 years of experience with asm/gdb/C/C++ so I thought it will be easy.
In C yes, in C++ ... :(

The problem is the constuction order. With the code on the tutorial the call order is wrong.
Dependencies between classes are not maintained.
I have 3 global objects and constuction order is exactly the opposite needed.
¿Is this a concidence?
Is there any way to fix it?
Any documentation about the issue (gcc c++ construction call order)?

Thanks in advance :)

PS: sorry for my poor english :)

Re: C++ contruction order

Posted: Wed Apr 29, 2009 6:39 am
by Solar
DrLecter wrote:Any documentation about the issue (gcc c++ construction call order)?
Probably. Somewhere. Then again, perhaps not. None that I found, anyway.

Re: C++ contruction order

Posted: Wed Apr 29, 2009 8:17 am
by skyking
You have the init_priority attribute in GCC. Also IIRC the order of calls to global constructors within one translation unit is well defined in the standard (in the order they appear).

If you don't want to rely on gcc extensions you could construct the objects on demand:

Code: Select all

C*  some_obj()
{
  static C obj;
  return &obj;
}
which is guaranteed to not run the constructor for obj until the first time some_obj is called (this, as you might suspect, need runtime support).

Re: C++ contruction order

Posted: Thu Apr 30, 2009 12:19 am
by DrLecter
I don't like global objects ;) but how do you implement cout them?

Re: C++ contruction order

Posted: Thu Apr 30, 2009 12:48 am
by DrLecter
The problem can be fixed with a custom INPUT(..) in the linker script but I don't like this hack.
I will try with some information from ld to get the work done automatically :)

CONSTRUCTORS

When linking using the a.out object file format, the linker uses an unusual set construct to
support C++ global constructors and destructors. When linking object file formats which do
not support arbitrary sections, such as ECOFF and XCOFF, the linker will automatically rec-
ognize C++ global constructors and destructors by name. For these object file formats, the
CONSTRUCTORS command tells the linker to place constructor information in the output sec-
tion where the CONSTRUCTORS command appears. The CONSTRUCTORS command is ignored for
other object file formats.
The symbol __CTOR_LIST__ marks the start of the global constructors, and the symbol
__DTOR_LIST marks the end. The first word in the list is the number of entries, followed by the
address of each constructor or destructor, followed by a zero word. The compiler must arrange
to actually run the code. For these object file formats gnu C++ normally calls constructors from
a subroutine __main; a call to __main is automatically inserted into the startup code for main.
gnu C++ normally runs destructors either by using atexit, or directly from the function exit.
For object file formats such as COFF or ELF which support arbitrary section names, gnu C++ will
normally arrange to put the addresses of global constructors and destructors into the .ctors and
.dtors sections. Placing the following sequence into your linker script will build the sort of
table which the gnu C++ runtime code expects to see.
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
If you are using the gnu C++ support for initialization priority, which provides some control
over the order in which global constructors are run, you must sort the constructors at link time
to ensure that they are executed in the correct order. When using the CONSTRUCTORS com-
mand, use SORT(CONSTRUCTORS) instead. When using the .ctors and .dtors sections, use
*(SORT(.ctors)) and *(SORT(.dtors)) instead of just *(.ctors) and *(.dtors).
Normally the compiler and linker will handle these issues automatically, and you will not need
to concern yourself with them. However, you may need to consider this if you are using C++ and
writing your own linker scripts.