TITLE: stripping unused globals (Newsgroups: comp.lang.c++.moderated, 14 May 97) CLAMAGE: Steve Clamage > |> I assume you mean that the implementation is elminating global objects > |> that appear to be unreferenced. That is disallowed by the standard > |> (and the ARM) if the constructor or destructor have side effects. > |> > |> Draft standard section 3.7.1 "Static storage duration": > |> "If an object of static storage duration has initialization or a > |> destructor with side effects, it shall not be eliminated even if it > |> appears to be unused, except that a class object or its copy may be > |> eliminated as specified in 12.8." (Section 12.8 involves copying > |> objects, and does not apply to this case.) KANZE: James Kanze > How does this coexist with section 3.6.2/3: "It is > implementation-defined whether the dynamic initialization of an object > of namespace scope with static storage duration is done before the first > statement of main or deferred to any point in time after the first > statement of main but before the first use of a function or object > defined in the same translation unit." CLAMAGE: Good question. I think the two sections refer to slightly different things. I also think the paragraph I quoted is redundant, given the discussion in chapter 3 about the abstract machine and what we usually call the "as-if" rule. The section I quoted says that even though unreferenced objects can otherwise be elminated under the "as-if" rule (if they are not referenced you can't tell whether they are included or not), side effects in initialization or destruction prevent their elimination. You can tell by observing side effects whether they were included.) The section you quoted is part of a very messy part of the draft, which tries to specify what you can and cannot expect about separate translation units. A lot of people have worked on this subject over the years without ever coming up with a completely satisfactory solution. (Given the crufty model of separate translation units inherited from C, the subject is very difficult. If we abandoned C compatibility we could probably find a model with nicer semantics.) Suppose we have an unreferenced static object X in a translation unit, and its constructor has side effects. We know that the C++ implementation cannot eliminate the object, but exactly how we get the module containing the object into our executable program is outside the realm of the standard. Let's assume we arrange for the module to be included somehow. (This is the first portability problem.) If the module contains an object or function that is referenced by the program, we also know that X must be initialized not later than the first such reference. Your question is what happens if no object or function in that module is referenced by the program. I believe the implementation satisfies the standard's requirements even if the constructor (and thus also the destructor) is never called. That is: 1. the object is not omitted, and 2. the provisions about when to call the constructor are satisfied vacuously. (The call can be put off until an event occurs which never does occur.) If you are not satisfied by that analysis, consider this program: File1: ... T t; // object's constructor has side effects int f() { ... } File2: ... int main(int argc, char** argv) { if( argc > 2 ) throw 0; return f(); } Here we have two translation units linked together. Function main references function f in File1, and so 't' must be initialized before the call to f. But sometimes function f is never called. Surely the implementation is conforming if in that case 't' is never constructed. The original example IMHO just follows this example to its logical conclusion. For portable programs you should not assume that a static object is initialized unless you do something to force access to the module where it is defined. This may be yet another reason not to use namespace-scope static objects whose order of initialization matters.