From: thansen@diku.dk
Newsgroups: gnu.g++.bug
Subject: Bug: "static String a" (file scope) is not initialized
Date: 25 Jan 1993 20:40:04 -0500
Organization: GNUs Not Usenet
Distribution: gnu

I sent this to bug-lib-g++@prep.ai.mit.edu, and Per Bothner
(bothner@cygnus.com) told me it belonged here:

Bug Report.  Summary: When declaring "static String a" in file scope,
"a" is not initialized. "String a" works correctly.

I am not sure if this is a bug of libg++ or gcc, please tell me if I
mailed the report to the wrong place.

I am using g++ v2.3.3 and libg++ v2.3 on a SUN Sparcstation 1.  Want
to declare a Variable "static String rapstd" with file scope, but it
is not initialized, String::String() is not called.  If I declare it
as plain "String", the constructor is called.  I have included the
piece of code which contains the relevant parts.  It's very
frustrating that the included piece of code *does* work correctly when
I compile it without the rest of the files.  I have not been able to
reproduce this error in a smaller context.  I have tried to add all
the information I could think of.  Is there something I have forgotten
that may influence the code?

Here's the code:  

    /* main module: rap.C */

    #include <iostream.h>
    #include <String.h>
    #include "etc..."

    extern "C" char * getenv( const char *name );
    #define RAPLIB "/home/ask2/thansen/Propra/Source/raplib"

    typedef String fileName ;

    fileName searchpath ; // line 100 in original rap.C
    fileName raperror ;
    fileName raphelp ;
    static fileName rapstd ; // line 116 in original rap.C
    static fileName rapinit ;

    /* more declarations and functions */

    static void SetPath () {
      searchpath = getenv ( "RAPLIB" ) ;
      rapinit = String ( getenv ( "HOME" ) ) + "/.raprc" ;

      if ( searchpath == "" ) {
	raperror = RAPLIB ;
	raphelp = RAPLIB ;
	rapstd = RAPLIB ;
	searchpath = RAPLIB ;
      } else {
	raperror = searchpath ;
	raphelp = searchpath ;
	rapstd = searchpath ;
      }
      raperror += "/raperror" ;
      raphelp += "/raphelp" ;
      rapstd += "/rapstd" ;
    }

    /* ... more functions ... */

    int main ( int argc, char* argv[] ) {
      cmdDescr comd ;
      Boolean error = false ;
      cout << "RAP System " << RAPVersion << " " << OS
        << "    (C) 1990, 1991 Universitaet Passau\n\n" ;
      SetPath () ;
      /* any line to check the values of rapstd and rapinit, e.g.
       * cout << "rapstd: " << rapstd << "\nrapinit: " << rapinit
       *      << "\nraphelp: " << raphelp << "\n" ;
       */
    }

    /* in the header files */

    #define PATCHLEVEL "0"
    #define RAPVersion ( String ( "0.0." ) + PATCHLEVEL )
    #define OS "for SunOS"

    class Boolean {
    private:
      int b ;
    public:
      Boolean ( int i = 0 ) ;
      operator int () const ;
    } ;

    enum command { helpCmd, nopCmd, /* ..., */ exitCmd } ;

    typedef optDescr* optPtr ;
    typedef valDescr* valPtr ;

    struct cmdDescr {    
      command c ;
      optPtr o ;
      valPtr p ;
    } ;

The whole program executes correctly if I remove the two "static"s
before "rapstd" and "rapinit".  Here's what gdb gives for the version
with static:

    (gdb) break SetPath
    Breakpoint 1 at 0x54834: file ./rap.C, line 133.
    (gdb) run
    Starting program: /net/ask/home/ask2/thansen/Propra/Source/rap 
    RAP System 0.0.0 for SunOS    (C) 1990, 1991 Universitaet Passau


    Breakpoint 1, SetPath () at ./rap.C:133
    133       searchpath = getenv ( "RAPLIB" ) ;
    (gdb) print rapstd
    $1 = {rep = 0xad878}
    (gdb) print &_nilStrRep
    $2 = (StrRep *) 0x82528
    (gdb) print *rapstd.rep 
    $3 = {len = 10, sz = 55800, s = {"\000"}}
    (gdb) print raperror
    $4 = {rep = 0x82528}
    (gdb) print rapstd.OK()
    String Error: invariant failure

    Program received signal 6, Abort
    0xf775eb20 in kill ()
    The program being debugged stopped while in a function called from GDB.
    The expression which contained the function call has been discarded.
    Unable to restore previously selected frame.

It looked like the constructor String::String() was not called for
"rapstd", so I tried this:

    (gdb) break rap.C:100
    Breakpoint 3 at 0x58c64: file ./rap.C, line 100.
    (gdb) break rap.C:116
    Breakpoint 4 at 0x58c94: file ./rap.C, line 116.
    (gdb) run
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /net/ask/home/ask2/thansen/Propra/Source/rap 

    Breakpoint 3, _GLOBAL_$I$searchpath () at ./rap.C:100
    100       fileName /*@THH*/ searchpath ;
    (gdb) print &searchpath
    $3 = (struct String *) 0x824d4
    (gdb) s
    String::String (this=0x824d4) at ./String.h:465
    ./String.h:465: No such file or directory.
    (gdb) cont
    Continuing.

    Breakpoint 4, _GLOBAL_$I$searchpath () at ./rap.C:117
    117       static fileName /*@THH*/ rapinit ;
    (gdb) print &rapinit
    $4 = (struct String *) 0x82518
    (gdb) s    
    String::String (this=0xaa210) at ./String.h:465
    ./String.h:465: No such file or directory.
    (gdb) n
    _GLOBAL_$I$searchpath () at ./rap.C:122
    122       static void    PutL ( flist*, fileName /*@THH*/ ) ;
    (gdb) print rapinit
    $5 = {rep = 0x0}
    (gdb) print searchpath
    $6 = {rep = 0x82528}

>From file String.h, line 464-465:
    inline String::String() 
      : rep(&_nilStrRep) {}

Shouldn't "rapinit" be "{rep = 0x82528}"?  

That's all useful information I can think of.  If I have forgotten any
useful information, please tell me.

Best regards,
	Thorbjoern Hansen

-- 
Thorbjoern Hansen, thansen@diku.dk, hansen@forwiss.uni-passau.de
  "Mystics are all a bit funny in the head anyway, which is why the
  church locks them all up in mental hospitals and euphemistically calls
  these institutions monasteries." -- Shea & Wilson, "Illuminatus!"