Topic: init of static objects


Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/06/13
Raw View
In article <rac-0606950943130001@intrigue.intrigue.com>,
Robert Coie <rac@intrigue.com> wrote:
>// header
>struct A { A(); };
>typedef void (*pFv)();
>void f();
>pFv g();
>
>// file1
>#include "header"
>#include <iostream>
>A::A() { cout << "hello" << endl; }
>
>// file2
>#include "header"
>A a;
>void f()
>{
>}
>
>// file3
>#include "header"
>pFv g()
>{
>   return &f;
>}
>
>// file4
>#include "header"
>int main()
>{
>   pFv   p = g();
>   (*p)();
>   return 0;
>}
>
>As I see it, the act of taking the address of f in file3 insures that
>file2 will not be stripped by the linker.  Is an implementation required
>to call A::A?

 Yes.

>If so, does such an implementation currently exist?

 I do not understand, I cannot imagine any implementation
that does not call A::A().

>I
>would think this would be devilishly difficult without abandoning deferred
>initialization.

 I do not understand. In order for this program
to work, the address of f() is taken.

 At least on DOS systems, what happens is the linker
will find f() in a translation unit. It loads the translation
unit. In that translation unit there exists a global
instance of A which requires initialisation, and the
system must schedule the invocation of the constructor of A().

 AFAIK I have never used a system on which this
doesn't work.

------------------------------------------------------------------------
EXCUSE thse lines, my brain dead news server requires
more "new" text than quoted text in an article.

I have asked to have this problem fixed.

Please lets not let stupid computer software take over
from human responsibility.
------------------------------------------------------------------------

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/06/05
Raw View
John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:
: In article <3q550m$b02@vishnu.jussieu.fr>,
: Fabrice Clerc <clerc@gla.ecoledoc.ibp.fr> wrote:

: Note that a global registry object is VERY DANGEROUS.
: There is no way to ensure it is initialised before it is needed.

: A work around is to use a _pointer_ to such an object,
: and have each class registering itself check of the pointer
: is 0, and if so create the object.
: Getting rid of the object is then kind of tricky -- I think
: it requires using "atexit()".

Or a static local variable in a function which returns the address
of (or a reference to) the object.

--
        Tony Cook - tony@online.tmx.com.au
                    100237.3425@compuserve.com





Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1995/06/06
Raw View
John Max Skaller (maxtal@Physics.usyd.edu.au) wrote:

|> Note that a global registry object is VERY DANGEROUS.
|> There is no way to ensure it is initialised before it is needed.

Sure there is.  There are at least two ways:

1. Declare it in the same module as main, and don't need it before main
is called.

2. Arrange that everything works when the static objects are initialized
to zero.

In particular, I always design my registry classes so that 2 is true.

The objects (classes) to be registered are a more difficult problem.  If
all else fails, 1 remains as a solution.  In practice, I've yet to run
across a system where just making sure that they weren't in a DDL didn't
suffice.

|> A work around is to use a _pointer_ to such an object,
|> and have each class registering itself check of the pointer
|> is 0, and if so create the object.

This is basically a variant of 2.  I just prefer to see the logic in the
registry, and not in the user objects.
--
James Kanze           (+33) 88 14 49 00          email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle--
                             --Beratung in industrieller Datenverarbeitung





Author: rac@intrigue.com (Robert Coie)
Date: 1995/06/06
Raw View
In article <D9DB5C.JGA@ucc.su.OZ.AU>, maxtal@Physics.usyd.edu.au (John Max
Skaller) wrote:

: In article <3q550m$b02@vishnu.jussieu.fr>,
: Fabrice Clerc <clerc@gla.ecoledoc.ibp.fr> wrote:
: >What about unreferenced global objects whose ctors have side-effects ?
: >
: >Does the WP specify whether unreferenced global objects whose ctors have
: >side effects must be constructed ?
:
:         Yes it says so -- although it is unnecessary to do so.
: Constructors of un-referenced objects which do not have side
: efffects can be eliminated no matter what the WP says, by the
: "as if" rule -- if you can't tell whether it has been eliminated
: or not you can eliminate it.
:
:         On the other hand there is no need to say constructors
: of unreferenced objects _with_ side-effects must not be
: eliminated, because an object defined in a translatioin unit
: is an object of the translation unit -- its there, it IS
: part of the program.
:
:         That is the rule is really just a reassurance.
:
: >On some systems, these objects
: >are never constructed (especially if you place them in libraries) !
:
:         Do not get confused between
:
:         1) eliminating a global _from_ a specified translation unit
:         2) not linking in a particular translation unit
:
: (1) is NOT allowed. (2) is determined by the implementor.

// header
struct A { A(); };
typedef void (*pFv)();
void f();
pFv g();

// file1
#include "header"
#include <iostream>
A::A() { cout << "hello" << endl; }

// file2
#include "header"
A a;
void f()
{
}

// file3
#include "header"
pFv g()
{
   return &f;
}

// file4
#include "header"
int main()
{
   pFv   p = g();
   (*p)();
   return 0;
}

As I see it, the act of taking the address of f in file3 insures that
file2 will not be stripped by the linker.  Is an implementation required
to call A::A?  If so, does such an implementation currently exist?  I
would think this would be devilishly difficult without abandoning deferred
initialization.

Robert Coie                              rac@intrigue.com
Implementor, Intrigue Corporation     AppleLink: INTRIGUE





Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/30
Raw View
In article <3q550m$b02@vishnu.jussieu.fr>,
Fabrice Clerc <clerc@gla.ecoledoc.ibp.fr> wrote:
>What about unreferenced global objects whose ctors have side-effects ?
>
>Does the WP specify whether unreferenced global objects whose ctors have
>side effects must be constructed ?

 Yes it says so -- although it is unnecessary to do so.
Constructors of un-referenced objects which do not have side
efffects can be eliminated no matter what the WP says, by the
"as if" rule -- if you can't tell whether it has been eliminated
or not you can eliminate it.

 On the other hand there is no need to say constructors
of unreferenced objects _with_ side-effects must not be
eliminated, because an object defined in a translatioin unit
is an object of the translation unit -- its there, it IS
part of the program.

 That is the rule is really just a reassurance.

>On some systems, these objects
>are never constructed (especially if you place them in libraries) !

 Do not get confused between

 1) eliminating a global _from_ a specified translation unit
 2) not linking in a particular translation unit

(1) is NOT allowed. (2) is determined by the implementor.

Note that a global registry object is VERY DANGEROUS.
There is no way to ensure it is initialised before it is needed.

A work around is to use a _pointer_ to such an object,
and have each class registering itself check of the pointer
is 0, and if so create the object.
Getting rid of the object is then kind of tricky -- I think
it requires using "atexit()".

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,
        81A Glebe Point Rd, GLEBE   Mem: SA IT/9/22,SC22/WG21
        NSW 2037, AUSTRALIA     Phone: 61-2-566-2189





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/25
Raw View
In article 2505952315070001@adsoftware.highway1.com.au, dent@highway1.com.au (Andy Dent) writes:
>In article <3q18ms$cs6@hamlet.ot.com.au>,
>jamesb@I_should_put_my_domain_in_etc_NNTP_INEWS_DOMAIN (James Brister)
>wrote:
>
>>Is it guaranteed that a static object's constructors will be called
>>before main() starts, or only before it's accessed?
>What's the difference, from a user view? Are you embedding some
>side-effects in the constructor?
>
>ARM p92 says "Init of a local object with storage class statis is done the
>first time control passes through its declaration." I'm not sure what this
>means for a file-scope static object. I have a vague memory of an example
>showing this occurring before main() but in an indeterminate order
>(amongst the .cpp files). I just tried to find the reference in the c++
>FAQ and Coplien but couldn't.

In this group we should refer to the draft standard for answers to
questions of this sort.

The original question was a little imprecise. There are two kinds of
static objects: "local static", which are defined inside a function,
and "non-local static", which are not defined inside any function.
"Static" here means "static storage duration", not necessarily having
the "static" keyword in its declaration. Non-local statics include
extern (so-called "global") objects.

A local static object is initialized the first time control passes
through its definition. (Thus, it might never be initialized.)

The wording describing intialization of non-local statics is still
undergoing debate. The ARM and draft standard say that such an object
is initialized before any function or object in its translation unit
is referenced. This seems to promise a reliable way to force the order
of initialization via calling functions in other translation units from
initializers, but that was not intended and isn't implemented anywhere.

You can depend on non-local static objects being intialized before they
are referenced, providing that first reference occurs after main has
been entered. (Not what the standard says, but how implementations work.)
As a practical matter, non-local statics which are not in dynamic
libraries are usually all initialized prior to the execution of the
first statement in main. (Technically, you should not depend on that,
since the standard does not require it.)

If you are concerned about writing reliable, portable code, you should
not depend on any particular order of initialization of non-local
static objects in different translation units.

You can eliminate the problem ENTIRELY by simply not using non-local
static objects at all. For example, instead of creating an extern
static object, write an extern function that returns a reference to
an object which is either a local static or on the heap.

Instead of
 T myobject;
write
 T& myobject() {
  static T t;
  return t;
 }
or
 T& myobject() {
  static T* t = new T;
  return t;
 }

No matter how or where myobject is first called, the T object will be
created at that time. You will have a problem only if your DESIGN contains
a circular dependency; you don't have to write error-prone code to enforce
a simple dependency.
---
Steve Clamage, stephen.clamage@eng.sun.com







Author: clerc@gla.ecoledoc.ibp.fr (Fabrice Clerc)
Date: 1995/05/26
Raw View
What about unreferenced global objects whose ctors have side-effects ?

Does the WP specify whether unreferenced global objects whose ctors have
side effects must be constructed ? On some systems, these objects
are never constructed (especially if you place them in libraries) !

[context: I use global objects to register 'pseudo-constructors'
(a function which simply returns a new instance). The application
never knows the 'real type' of the object but interacts with it using
virtual functions only - these objects have a common base class].

thanks

---
Fabrice Clerc
clerc@gla.ecoledoc.ibp.fr





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/05/26
Raw View
In article b02@vishnu.jussieu.fr, clerc@gla.ecoledoc.ibp.fr (Fabrice Clerc) writes:
>What about unreferenced global objects whose ctors have side-effects ?
>
>Does the WP specify whether unreferenced global objects whose ctors have
>side effects must be constructed ? On some systems, these objects
>are never constructed (especially if you place them in libraries) !

The compiler is not supposed to optimize away a named object which has a
non-trivial constructor or destructor. (If it has side effects, it is
non-trivial.)

In addition, a non-local static object is supposed to be initialized not
later than the first use of an object or function in its translation unit.
(There are problems with this, but lets ignore them.) The reason for
allowing a delay in the initialization is to allow useful dynamic libraries;
they don't have to be initialized until they are used.

But what if you have a global object whose translation unit is never
referenced? (If a tree falls in the forest ...) I believe the C++
implementation is not required (but is allowed) to create and destroy
the object. Whether it is required to or not, I would not depend on it
happening. As I've written elsewhere, you are better off not using
static objects at all if they require non-trivial construction or
destruction, and if you care in what order things happen.

---
Steve Clamage, stephen.clamage@eng.sun.com