[comp.lang.c++] Help !

dmg@ssc-vax.UUCP (David Geary) (07/06/89)

  Here's something interesting:

First, the file works.cxx:

----------------------------------------------------------------------
#include "//ernie/user/geary/c++/include/stream.hxx"        // c++ i/o

class junk { public: junk() { puts("Constructing Junk"); } };

junk myjunk;

main() { }
----------------------------------------------------------------------

When I compile and run, I get:

$ works
Constructing Junk
$

(In other words, everything is ok).  However, watch this:

The file noworks.cxx:

----------------------------------------------------------------------
#include "//ernie/user/geary/c++/include/stream.hxx"        // c++ i/o

class junk { public: junk() { cout << "Constructing Link\n"; } };

junk myjunk;

main() { }
----------------------------------------------------------------------

When I compile and run, I get:

$ noworks
Segmentation Fault
$

(In other words, everything is NOT ok ;-).  The only difference
between the two is that I use puts() in works.cxx, and use
cout << in noworks.cxx.  How, watch this:

The file worksagain.cxx

----------------------------------------------------------------------
#include "//ernie/user/geary/c++/include/stream.hxx"        // c++ i/o

class junk { public: junk() { cout << "Constructing Link\n"; } };

main()
{
junk myjunk;
}
----------------------------------------------------------------------

When I compile and run, I get:

$ worksagain
Constructing Junk
$

So now, I can use cout << ... but I cannot have the object myjunk
external, it has to be in main().

  Can anybody provide an explanation as to why this is happening?

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace, Seattle                 ~ 
~ "I wish I lived where it *only* rains 364 days a year" ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

beard@ux1.lbl.gov (Patrick C Beard) (07/06/89)

The first case works because you are calling a standard C function to
do console i/o, which requires no explicit initialization to work.

The third case works because all static constructors (which the
iostream classes have) are called before you use "cout".

The second case doesn't work because of ordering problems in the calling
of static constructors.  If the stream's constructor was called first,
it would work.

Anyway, it's really bad practice to write code that depends on the order
of calling of static constructors.  Don't do it.  In fact, I think
static constructors are nothing but trouble (mho, of course).

I hope this explains your problem.

Patrick Beard
beard@lbl.gov

vasta@apollo.COM (John Vasta) (07/07/89)

In article <2774@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>
>  Here's something interesting:
>  [ ... ]
>The file noworks.cxx:
>----------------------------------------------------------------------
>#include "//ernie/user/geary/c++/include/stream.hxx"        // c++ i/o
>
>class junk { public: junk() { cout << "Constructing Link\n"; } };
>
>junk myjunk;
>
>main() { }
>----------------------------------------------------------------------
>
>When I compile and run, I get:
>
>$ noworks
>Segmentation Fault
>
>  Can anybody provide an explanation as to why this is happening?

The cout object from the stream library must be initialized when the
program starts up. So does your myjunk object. The order of execution
of constructors for static objects in different modules is not defined.
It looks like your object is getting attention first in this case,
and its constructor is trying to use an uninitialized stream object.

Although some people have found ways of determining or even controlling
the execution order of static constructors/destructors, these techniques
are not portable, so I'd advise you not to count on them. Making the
object automatic (e.g. local to main) makes sure that all static objects
are initialized first. If you need global visibility for an object which
depends on other static objects being initialized, you can create
the object dynamically (using new) and put a pointer to it in file scope.

-- 
John Vasta                Apollo Computer (division of Hewlett Packard)
vasta@apollo.com          M.S. CHA-01-LT
(508) 256-6600 x6362      330 Billerica Road, Chelmsford, MA 01824
UUCP: {decwrl!decvax, mit-eddie, attunix}!apollo!vasta

ark@alice.UUCP (Andrew Koenig) (07/07/89)

In article <4443be62.1ad5a@apollo.COM>, vasta@apollo.COM (John Vasta) writes:

> The cout object from the stream library must be initialized when the
> program starts up. So does your myjunk object. The order of execution
> of constructors for static objects in different modules is not defined.

C++ 2.0 does two things to make this less of a bother.

First, the 2.0 stream library goes to some trouble to ensure
that it works correctly even in the face of static constructors
and destructors.

Second, if you have a static object that is local to a function,
that object will be initialized no later than the first time that
the flow of control passes through that declaration, even if
that function is called from a static constructor.

Example:

	struct T {
		T();
	};

	void f()
	{
		static T t;
	};

In this example, T::T() will be called to initialize t no later than
the first time f() is executed.
-- 
				--Andrew Koenig
				  ark@europa.att.com

wmm@sdti.com (0006-William M. Miller(0000)) (07/07/89)

In article <2774@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>So now, I can use cout << ... but I cannot have the object myjunk
>external, it has to be in main().
>
>  Can anybody provide an explanation as to why this is happening?

Yes, you've been bitten by the "undefined static constructor order" bug.
"cout" is a static object of class "ostream" which is defined in the
library code somewhere.  "myjunk" (in the nonworking example) is a static
object of class "junk" which is defined in your program.  When static
objects are defined in different files, the order in which their
constructors are invoked is not defined (within a file, it's done in
declaration order).  In your case, "myjunk" is being constructed before
"cout," so saying "cout <<" in the constructor uses an uninitialized
object.
-- 
Non-disclaimer:  My boss and I always see eye-to-eye (every time I look in
the mirror).

...!genrad!mrst!sdti!wmm

rds@goanna.oz.au (Rowan D. Stevens) (01/24/90)

 ----  HELP!  ----

I am looking for information about either a user interface methodology, a
name of a research paper, an actual CASE tool or development environment, or
anything which might help me to locate the following:-

A tool or method which will allow a user interface to be developed visually
(similiar to Microsoft's Dialog Box Editor) but will output the operational
interface shell in some object-oriented programming type language (ie. c++)
The method should allow modelling of window-oriented and text user interfaces.
Anything close to this, I would still like to hear about.

If someone out there is carrying out research in this or a similar area, then I
would be very interested in talking further about this.

I can be contacted at:

	Royal Melbourne Institute of Technology
	C/-Department of Computer Science
	GPO BOX 2476V
	Melbourne, Vic 3001
	Australia

	Phone: +61-3-660-3216  
	ACSnet: rds@goanna.rmit.oz

Much appreciated!

Regards --> Rowan Stevens

shiao@cunixf.cc.columbia.edu (Dennis Shiao) (04/11/90)

Does anyone have any information(general->specific) on Object Oriented 
Programming ? A final project in one of my classes entails writing a 
processor to take C-- code (C, minus some functionality -- a pseudo language)
and produce from it valid C code.

Topics of Interest:
Symbol Tables
Parse Trees
Object Oriented Programming 
Lex
Yacc


Thanks a lot....

Dennis

internet --> shiao@cunixf.cc.columbia.edu
bitnet ----> shiao@cunixf.BITNET