[gnu.g++] NIH library with g++ problems

gas@cs.nott.ac.uk (Alan Shepherd) (02/14/90)

I've been working on getting the nih library 2.04 to compile with g++.
With some help from Michael Tiemann, I've managed to get the library
to compile and a fair number of the tests to work.  However, there are still
a couple of areas I'm having problems with.  If anyone has any ideas,
please let me know.

1. simplest one:  libnihcl.a has it's own _main which initialises the 
various pointers etc, creates static objects and all the other usual things.
Unfortunately g++ seems to include it's own _main which doesn't
initialise the NIH lib.  My solution (which is 100% effective - I think!)
is to include the call to NIHCL::initialize() as the first command after
main() {.  Is there a better way ?  Can I make g++ use the _main from
libnihcl.a instead of it's own (from gnulib3) ?

2. this is more difficult:

Several objects have methods which return objects rather than
references or pointers to objects.  I surmise that this is because
firstly that new objects need to be made in for example a Set union
operator and that the system will take care of deleting objects which
aren't explicitly created with new.  This must work with AT&T, but then
the static Object* nil was also declared as static Object* const nil, and
this failed with g++, because the initialisation tries to write to it. i.e.
illegal (?) code worked with AT&T, but not with gnu !

However, g++ warns me about bitwise copying with methods which return
objects and I've discovered that some of them don't work properly.  For
example, Dictionary has a method 'asBag' inherited from Collection and declared
like so:

     Bag Collection::asBag() const

I've checked the bag this produces internally just before returning
and found that element at position 1 is 

    (Object *&) (0x4aa2c &) = 0x49720 (i.e. the nil object)

yet after returning from the method, the Bag which has been bitwise
copied has the following for it's first element:

    (Object*&) (0x4aa2c &) = 0x47694

Naturally this causes a segmentation fault since it later thinks it
has a real object when it hasn't.

Does anyone have any ideas ?

Alan Shepherd

kgorlen@nih-csl.UUCP (Keith Gorlen) (02/17/90)

In article <24489@robin.cs.nott.ac.uk>, gas@cs.nott.ac.uk (Alan Shepherd) writes:
-> I've been working on getting the nih library 2.04 to compile with g++.
-> With some help from Michael Tiemann, I've managed to get the library
-> to compile and a fair number of the tests to work.  However, there are still
-> a couple of areas I'm having problems with.  If anyone has any ideas,
-> please let me know.
-> 
-> 1. simplest one:  libnihcl.a has it's own _main which initialises the 
-> various pointers etc, creates static objects and all the other usual things.
-> Unfortunately g++ seems to include it's own _main which doesn't
-> initialise the NIH lib.  My solution (which is 100% effective - I think!)
-> is to include the call to NIHCL::initialize() as the first command after
-> main() {.  Is there a better way ?  Can I make g++ use the _main from
-> libnihcl.a instead of it's own (from gnulib3) ?

Sounds like you can just modify a copy of the g++ version of _main()
to call NIHCL::initialize() just before it returns, and place it in
libnihcl.a.

-> 2. this is more difficult:
-> 
-> Several objects have methods which return objects rather than
-> references or pointers to objects.  I surmise that this is because
-> firstly that new objects need to be made in for example a Set union
-> operator and that the system will take care of deleting objects which
-> aren't explicitly created with new.

That is correct.  The return object is a compiler-generated temporary,
which it is responsible for deleting.

-> ... This must work with AT&T, but then
-> the static Object* nil was also declared as static Object* const nil, and
-> this failed with g++, because the initialisation tries to write to it. i.e.
-> illegal (?) code worked with AT&T, but not with gnu !

I don't understand the connection, but the nil pointer is defined as:

	Object*	const Object::nil = 0;

I wanted to write something like

	static Nil nil_object;
	Object* const Object::nil = &nil_object;

or

	Object* const Object::nil = new Nil;

but cfront 2.0 doesn't handle these correctly.  So I had to do it by
hand, casting away the const-ness of a pointer to nil:

	Object** nilp = (Object**)&Object::nil;	// create the nil object and
	*nilp = new Nil;			// initialize the pointer to it	

-> However, g++ warns me about bitwise copying with methods which return
-> objects and I've discovered that some of them don't work properly.  For
-> example, Dictionary has a method 'asBag' inherited from Collection and declared
-> like so:
-> 
->      Bag Collection::asBag() const
-> 
-> I've checked the bag this produces internally just before returning
-> and found that element at position 1 is 
-> 
->     (Object *&) (0x4aa2c &) = 0x49720 (i.e. the nil object)
-> 
-> yet after returning from the method, the Bag which has been bitwise
-> copied has the following for it's first element:
-> 
->     (Object*&) (0x4aa2c &) = 0x47694
-> 
-> Naturally this causes a segmentation fault since it later thinks it
-> has a real object when it hasn't.

The copy constructor Bag::Bag(const Bag&) is defined, so C++ should
never bitwise-copy a Bag, but call this constructor instead.  I
checked the definition of the Bag copy constructor, and it looks OK.
If g++ is doing a bitwise copy of a bag, that sounds like a g++ bug to
me.

-- 
	Keith Gorlen			phone: (301) 496-1111
	Building 12A, Room 2033		uucp: uunet!nih-csl!kgorlen
	National Institutes of Health	Internet: kgorlen@alw.nih.gov
	Bethesda, MD 20892