Thread overview
Order of initialization
Sep 27, 2001
Russ Lewis
Sep 27, 2001
Russell Borogove
Sep 27, 2001
Walter
Initialization Exceptions (was Order of initialization)
Sep 27, 2001
Russ Lewis
Sep 28, 2001
Walter
September 27, 2001
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))) ]


September 27, 2001
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
September 27, 2001
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))) ]
>
>


September 27, 2001
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))) ]


September 28, 2001
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
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))) ]
>
>