Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!rutgers!seismo!munnari!otc!mikem From: mikem@otc.UUCP Newsgroups: comp.lang.c++ Subject: Re: Some Questions (1) - Also a munch fix. Message-ID: <84@otc.OZ> Date: Sun, 8-Feb-87 22:17:18 EST Article-I.D.: otc.84 Posted: Sun Feb 8 22:17:18 1987 Date-Received: Tue, 10-Feb-87 03:55:57 EST References: <1207@hplabsc.UUCP> Organization: O.T.C. Systems Development, Australia Lines: 139 The first question asked by the "shy" person was: > Is there any reason that initialization of static members couldn't be > allowed. The version 1.1 compiler gives an error message when an > initializer is present for a static member, and "THE BOOK" claims (page > 275): > > No initializer can be specified for a static member, and it > cannot be of a class with a constructor. > > What is the technical reason for this? I have not been able to think > of any reason that this shouldn't be legal given that static variables > can be initialized. The reason is that include files containing the class definition could appear in multiple .c files, and there is no easy way of resolving which file actually "owns" the static member. (For ordinary static variables, they clearly only exist in a single file.) E.g: Consider the following include file "foo.h", and the two .c files "bar1.c", "bar2.c" ---------------------------------------------------------------------------- // foo.h class SomeClass { int i; public: SomeClass(int ii) { i = ii; } int show() { return i; } void set(int ii) { i = ii; } }; class Foo { static SomeClass sc(1); public: int show() { return sc.show(); } void set(i) { sc.set(i); } }; // (end foo.h) ---------------------------------------------------------------------------- // bar1.c #include "foo.h" ..... // (end bar1.c) ---------------------------------------------------------------------------- // bar1.c #include "foo.h" ..... // (end bar1.c) ---------------------------------------------------------------------------- The way that ctors on static variables are made to work is by generating a function like: _STI_whatever() // or something like that { // code to actually call the constructor for the variable. } At link time, the program "munch" examines the namelist, and if there are any _STI_* it puts these names into a variable "_ctors" which is an array of ptrs-to-fns. _main() then arranges to call everything appearing in _ctors. (_main() is called automatically at the start of main()). So the problem is that the #include "foo.h" in will result in _STI_* fns within bar1..c and bar2..c and _main() will therefore call the ctor twice, which is wrong. It may be possible to do it by having cfront generate the _ST functions with redundancy-resolving information built into the name: E.g: In bar1..c: _STS_7_bar1_c_Foo_sc() { // call ctor for Foo::sc } In bar2..c: _STS_7_bar2_c_Foo_sc() { // call ctor for Foo::sc } (where the "7" indicates where the filename information finishes, and the variable name starts, i.e: specifies where to look in the name for redundancy-resolving information.) It may then be possible for munch to recognize _STS prefixes and resolve the ambiguity so that only one of _STS_7_bar1_c_Foo_sc() and _STS_7_bar2_c_Foo_sc() are puts into _ctors. The trouble with this is that the current operation of munch (using nm) can't be guaranteed to work in all possible c linker environments. But this may be acceptable (C++ in some environments would then still have to generate a "sorry, not implemented" message). Personally, I do find it annoying not to have static class members with ctors. It's something that tends to arise in applications, and not so much when you're just writing libraries. Since I'm on the subject of munch, I may as well post a minor improvement to the version in 1.1: Currently, where the constructor for one static object uses another static object that also has a constructor, munch will tend to arrange that the constructors get called in the wrong order, with resulting inexplicable core dumps. This is because the order that the names appear in the namelist is in the CORRECT order, but munch uses a simple stacking arrangement when making _ctors, so the order gets reversed. (Note that this behaviour is correct for dtors, however.) The fix for munch.c is as follows: Add a declaration: sbuf* tail; where sbuf *ctor,*dtor are declared. Replace case 'I' in the switch by: case 'I': // ctors are handled fifo if (tail) tail = (tail->next = new sbuf(NULL,st)); else tail = ctor = new sbuf(NULL,st); Note that this cannot be considered a general answer to the problem, since the "munch" method as it stands depends heavily on the linker environment. Mike Mowbray Systems Development Overseas Telecommunications Commission (Australia) UUCP: {seismo,mcvax}!otc.oz!mikem ACSnet: mikem@otc.oz