[comp.lang.c++] Is this a bug?

sanders@boulder.Colorado.EDU (Bruce Sanders) (06/11/87)

When I compile and run the following C++ program, I get a segmentation fault.
	C++ version	<<cfront 1.2.1 2/16/87>>
	Sun OS version	3.3

// ----------------------------------------------------------------------------
#include <stream.h>

class c {
    char	*s;
public:
	c(char *string) { s = string; cerr << "constructor "; print(); }
//                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	void print() { cerr << s << "\n"; }
};

c global("global");

main()
{
	c local("local");
	c stat("static");
	global.print();
	local.print();
	stat.print();
}
// ----------------------------------------------------------------------------

adb gives the following output:

% adb a.out
core file = core -- program ``a.out''
SIGSEGV 11: segmentation violation
$c
__ostream__lshiftFPC__(0x20d60,0x20071) + 30
__STIjnk_c_() + 24
__main() + 14
_main(0x1,0xefffbbc,0xefffbc4) + e


If I comment out the two lines with "global" in them, everything works,
producing the following output:

% a.out
constructor local
constructor static
local
static

Alternatively, if I remove the cerr and print statements (indicated in
the comment) from the constructor, it works correctly, producing

% a.out
global
local
static

Is this a bug, or am I doing something illegal?

thanks
bruce

Bruce W. Sanders
Department of Computer Science
University of Colorado
Campus Box 430
Boulder, CO 80309-0430

(303) 492-8118

sanders@boulder

moore@ucbcad.berkeley.edu (Peter X Moore) (06/11/87)

This is not so much a bug, as an unavoidable feature of the way global 
constructors are implemented.  Both your object and cerr have global
constructors.  All global constructors are grouped together and called
IN ESSENTIALLY A RANDOM ORDER before main.  You are having the good fortune
of having your object's constructor called before cerr's constructor is
called, and so the code for << is core dumping as it tries to use an
unintialized data structure.  The immediate patch is to either use a local
stream variable instead of cerr or fall back to fprintf.  To fix the
general problem seems VERY tough, since it seemingly requires global
interdependacy analysis between all constructors.  Other languages must
face this problem, does anyone know what they do (or don't do)?

	Peter Moore
	moore@Berkeley.edu
	...!ucbvax!moore

jon@oddhack.caltech.edu (Jon Leech) (06/11/87)

Summary:

Expires:

Sender:

Followup-To:

Distribution:


In article <731@boulder.Colorado.EDU> sanders@boulder.Colorado.EDU (Bruce Sanders) writes:
>...
>If I comment out the two lines with "global" in them, everything works,
>producing the following output:
>...
>Alternatively, if I remove the cerr and print statements (indicated in
>the comment) from the constructor, it works correctly, producing
>...
>Is this a bug, or am I doing something illegal?

    The constructor for 'global' is probably being called before the
constructor for 'cerr'. Since cerr is declared in a different file,
it appears (see the reference manual 8.6.2) that you have no control
over the order in which these contructors are called, and thus should
not write code with this sort of dependency.

--
    Jon Leech (jon@csvax.caltech.edu || ...seismo!cit-vax!jon)
    Caltech Computer Science Graphics Group
    __@/

``There is only one spacefaring nation today. And it's not the United
    States, comrade!''

ark@alice.UUCP (06/12/87)

In article <731@boulder.Colorado.EDU>, sanders@boulder.UUCP writes:
-> 
-> When I compile and run the following C++ program, I get a segmentation fault.
-> 	C++ version	<<cfront 1.2.1 2/16/87>>
-> 	Sun OS version	3.3
-> 
-> // ----------------------------------------------------------------------------
-> #include <stream.h>
-> 
-> class c {
->     char	*s;
-> public:
-> 	c(char *string) { s = string; cerr << "constructor "; print(); }
-> //                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-> 	void print() { cerr << s << "\n"; }
-> };
-> 
-> c global("global");
-> 
-> main()
-> {
-> 	c local("local");
-> 	c stat("static");
-> 	global.print();
-> 	local.print();
-> 	stat.print();
-> }

It looks like what is happening is that the constructor for the variable
"global" is trying to print stuff before the I/O library is initialized.

This is not a bug.  The stream library relies on static constructors
for its initialization, and there is no guarantee that static
constructors will be executed in any particular sequence.

nadkarni@ashok.dec.com (04/13/90)

Am I doing something wrong or is this a bug in the compiler ? It appears 
as though the compiler tries to optimize by not copying the virtual table
function pointer when assigning an object to another. Unfortunately,
in this case it does not work. The compiler is Zortech C++ 2.06.
I expected to see the output

C
A
B

and instead saw

A
A
A

Could someone please confirm this is a bug (in my code or the compiler).
---------------------- code follows ------------------
#include <stream.hpp>

class C {
    public:
	virtual void output() {cout << "C\n";}
};

class A : public C {
    public:
	virtual void output() {cout << "A\n";}
};

class B : public C {
    public:
	virtual void output() {cout << "B\n";}
};

union AB {
    class B b;
    class C c;
    class A a;
};

main ()
{
    A a;
    B b;
    C c;
    AB ab;


    ab.c = c;
    ab.c.output();

    ab.a = a;
    ab.a.output();

    ab.b = b;
    ab.b.output();

}

Thanks,

/Ashok Nadkarni
Digital Equipment Corp.

williamt@athena1.Sun.COM (William A. Turnbow) (04/14/90)

In article <10259@shlump.nac.dec.com> nadkarni@ashok.dec.com writes:
>
>Am I doing something wrong or is this a bug in the compiler ? It appears 
>as though the compiler tries to optimize by not copying the virtual table
>function pointer when assigning an object to another. Unfortunately,
>in this case it does not work. The compiler is Zortech C++ 2.06.
>I expected to see the output
------
	Your program doesn't even compile on our compiler (AT&T 2.0.02).
It yields the following:
"tst8h.C", line 18: error:  member AB::b of class B with constructor in union
"tst8h.C", line 18: error:  member AB::c of class C with constructor in union
"tst8h.C", line 18: error:  member AB::a of class A with constructor in union
3 errors

	Just a guess, but there is a virtual field that gets auto initialized
when you declare an instance of the class.  By trying to do a union,
there would be three different constructors to call for the same memory
location, resulting in indeterminate behavior.  But this is just a
guess.

-wat-
***
    We felt the effects of herb were so dangerous that it was better
    to lie to the american public to save them rather than tell them
    the truth -- Partnership for a Drug Free America

berryc@arcturus.uucp (Craig D. Berry (x1710)) (03/26/91)

I have a class with a static member function:

class foo
{ ...
  public:
	static foo barfunc();	// Returns value of a foo object. 
  ...
}

Now, somewhere else, I try to use barfunc to initialize a foo:

  foo quux = foo::barfunc();

This doesn't work; the compiler wants a ( after foo::, for reasons
entirely mysterious to me.  Could be expecting one of foo's constructors,
I suppose...

However, 

  foo quux = (foo::barfunc());

works as intended; quux is created with the value returned by barfunc.
Am I missing something, or is my compiler (Turbo C++ 1.0) broken?

steve@taumet.com (Stephen Clamage) (03/29/91)

berryc@arcturus.uucp (Craig D. Berry (x1710)) writes:

|I have a class with a static member function:
|  class foo { public: static foo barfunc(); }
|Now, somewhere else, I try to use barfunc to initialize a foo:
|  foo quux = foo::barfunc();
|This doesn't work...
|Am I missing something, or is my compiler (Turbo C++ 1.0) broken?

This is a compiler bug.  I have the latest release, and the example works.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com