www.digitalmars.com         C & C++   DMDScript  

D - Order of initialization

reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I have a sticky situation I've encountered in a major C++ project that
I'm hoping D will be designed to solve.  It has to do with the order of
initialization of global data that is spread across multiple object
files.

bar.h:
   void Bar();

foo.cpp:
   Foo foo;

bar.cpp:
   Baz baz;
   void Bar()
   {
      baz.DoStuff();
   };

The problem here is that the constructor of Foo calls Bar().  However,
if I call Bar before the baz object is constructed, I get segfaults from
uninitialized pointers in baz.  Thus, baz *must* be constructed before
foo.  However, I can't find any way to force this to happen in C++,
other than include both foo and baz in the same .cpp file.  That's ugly
but workable.

What I'm thinking is that D should track the dependencies that arise
from the constructors used to build global data and ensure that the
objects are constructed in the right order (even if they come from
different modules).  If there are any circular dependencies, then post a
warning (or perhaps even an error) to the user.

Ofc, if anybody has a better way to do it that already works in C++, I'd
be glad to hear it.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Sep 27 2001
next sibling parent Russell Borogove <kaleja estarcion.com> writes:
Russ Lewis wrote:
 
 I have a sticky situation I've encountered in a major C++ project that
 I'm hoping D will be designed to solve.  It has to do with the order of
 initialization of global data that is spread across multiple object
 files.

 [...snip...]

 Ofc, if anybody has a better way to do it that already works in C++, I'd
 be glad to hear it.

My personal favored solution is to create a globals.cpp and put all global objects into it, in the correct initialization order. This strategy encourages minimal use of globals and the consolidation of related globals into classes, which IMO is a good thing. For the project I'm currently working on, the mandated solution is to create everything dynamically rather than statically, with some macrology to gloss over that fact: class Foo { ... // create the one-of-a-kind global Foo static void CreateInstance(); // get reference to the one-of-a-kind global Foo static Foo& GetInstance(); ... }; #define THEFOO Foo::GetInstance() main() { Foo::CreateInstance(); ... THEFOO.DoStuff(); ... } In practice, we have DEFINE_SINGLETON and IMPLEMENT_SINGLETON macros to automate the CreateInstance and GetInstance coding. This only works well when all your globals are actually singletons, of course, but when order of initialization is important, this will typically be the case. -Russell B
Sep 27 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
This is one of the great unsolved problems with C++. I think D can solve
this problem by keeping track of dependencies, but it won't be in the first
version. -Walter

Russ Lewis wrote in message <3BB38464.37B1BDB0 deming-os.org>...
I have a sticky situation I've encountered in a major C++ project that
I'm hoping D will be designed to solve.  It has to do with the order of
initialization of global data that is spread across multiple object
files.

bar.h:
   void Bar();

foo.cpp:
   Foo foo;

bar.cpp:
   Baz baz;
   void Bar()
   {
      baz.DoStuff();
   };

The problem here is that the constructor of Foo calls Bar().  However,
if I call Bar before the baz object is constructed, I get segfaults from
uninitialized pointers in baz.  Thus, baz *must* be constructed before
foo.  However, I can't find any way to force this to happen in C++,
other than include both foo and baz in the same .cpp file.  That's ugly
but workable.

What I'm thinking is that D should track the dependencies that arise
from the constructors used to build global data and ensure that the
objects are constructed in the right order (even if they come from
different modules).  If there are any circular dependencies, then post a
warning (or perhaps even an error) to the user.

Ofc, if anybody has a better way to do it that already works in C++, I'd
be glad to hear it.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]

Sep 27 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Another problem is handling of exceptions in this early code.  I could really
use some way to catch exceptions during the initialization and destruction
phases.  Ofc, the theory is that once my program is further along they won't
happen....but if they do, all we get is very uninformative coredumps.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Sep 27 2001
parent "Walter" <walter digitalmars.com> writes:
Exceptions that don't get caught all have a message associated with them,
and that message you'll get rather than a coredump. How explanatory the
message is will be up to the programmer.

Russ Lewis wrote in message <3BB3A6A0.3A9C2245 deming-os.org>...
Another problem is handling of exceptions in this early code.  I could

use some way to catch exceptions during the initialization and destruction
phases.  Ofc, the theory is that once my program is further along they

happen....but if they do, all we get is very uninformative coredumps.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]

Sep 27 2001