Xref: utzoo comp.lang.c++:9022 gnu.g++.bug:2153 gnu.g++.lib.bug:388 Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!wuarchive!cs.utexas.edu!rutgers!cunixf.cc.columbia.edu!cs.columbia.edu!kearns From: kearns@cs.columbia.edu (Steve Kearns) Newsgroups: comp.lang.c++,gnu.g++.bug,gnu.g++.lib.bug Subject: Re: problems with calling streams from constructors Message-ID: <1990Aug15.224436.10176@cs.columbia.edu> Date: 15 Aug 90 22:44:36 GMT References: <38170@ucbvax.BERKELEY.EDU> Reply-To: kearns@cs.columbia.edu (Steve Kearns) Followup-To: comp.lang.c++ Organization: Columbia University Department of Computer Science Lines: 46 In article <38170@ucbvax.BERKELEY.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes: > .... problems with initializing classes .............. > >The error occurs because global objects are initialized in the order >that object modules are handed to the linker, and cerr is not yet >initialized when the constructor for globalObj is called. As a result, >the ostream::operator<<(whatever) function dereferences null pointers. > >I know I can work around this problem by searching libg++ twice; I >also have a workaround that causes gnulib3.c to call the constructors >in reverse order. Reverse order always works when everything but main() >is obtained from a library and there are no circular dependencies. >Still, it's an inelegant hack. > >Ellis and Stroustrup (p. 21) discuss this problem and imply that this >problem has been solved for the iostream library. Can anyone discuss >how this is done? I have similar problems in other code. If there is >a standard fix, could it be implemented in libg++? I hate having to >avoid streams because a function may be called by a constructor. > Here is my solution, that works fine: The usual way to initialize a class, say class Foo, is to declare a special constructor for Foo, say Foo(int, char *), or a special friend class, say FooInit, and then declare "static Foo myIniter(5, "fake");" or "static FooInit myIniter;" in the class implementation file. In order to modify this system to initialize a class before it is used, just put the "static Foo myIniter(5, "fake");" or "static FooInit myIniter;" in the class HEADER (.h) file, instead, and make sure the initialization routine is smart enough to handle being called more than once. Then any file that uses Foo.h will cause the initialization routine to be called before any classes or code that depends on Foo. The only cost of this technique is a number of dummy variables being declared, which can take up extra space. One subtlety arises only in the following rare case: assume that Foo.cc (the implementation file) includes .h files which use this trick, but Foo.h does not include these .h files. Then the Foo constructor might be called before the classes Foo depends on are initialized. The only simple way around this problem is to make sure that Foo.h includes every .h file that Foo.cc does. In practice, Foo.cc usually includes just Foo.h, which includes all other .h files; therefore this issue rarely arises. -steve