🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

2 total messages Started by Andrew Thomas Thu, 03 Aug 1989 04:11
Destructor called too soon, Destructor not called - G++1.35
#325
Author: Andrew Thomas
Date: Thu, 03 Aug 1989 04:11
88 lines
2463 bytes
System:	uVax II , Ultrix 2.0

G++ 1.35

Problem: The destructors for class instances passed as return values
(rather than returning a pointer or reference) get called too soon if
only a member of the class is of interest.  Also, sometimes no
destructor is called at all.

Program: The following program exhibits both behaviours described
above:

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

class String
{
  char		*_ptr;
public:
  String (String&);
  String (char *);
  ~String();

  char*		ptr()			{ return (_ptr); }
};

String::String (String& old)
{
  char* a = new char[strlen(old._ptr) + 1];
  strcpy (a, old._ptr);
  _ptr = a;
  printf ("Constructing: %s (%x)\n", a, a);
}

String::String (char* old)
{
  char* a = new char[strlen(old) + 1];
  strcpy (a, old);
  _ptr = a;
  printf ("Constructing: %s (%x)\n", a, a);
}

String::~String()
{
  printf ("deleting %s (%x)\n", _ptr, _ptr);
  delete _ptr;
}

String my_func ()
{
  String	x = "Hello";
  return (x);
}

main ()
{
  printf ("Function: %s (%x)\n", my_func(), my_func());
  printf ("Function: %s (%x)\n", my_func().ptr(), my_func().ptr());
}

------------------------- cut -------------------------
The output of this program looks like:

Constructing: Hello (1c00)
Constructing: Hello (1c10)
deleting Hello (1c00)
Constructing: Hello (1c00)
Constructing: Hello (1c20)
deleting Hello (1c00)
Function: Hello (1c10)
Constructing: Hello (1c00)
Constructing: Hello (1c30)
deleting Hello (1c00)
deleting Hello (1c30)
Constructing: Hello (1c30)
Constructing: Hello (1c00)
deleting Hello (1c30)
deleting Hello (1c00)
Function: Hello (1c30)

Note only 6 destructors, and 8 constructors.  Also note that memory
address 1c30 is deleted with an automatically called destructor before
the String instance is actually used.
--

Andrew Thomas
andrewt@watsnew.waterloo.edu	Systems Design Eng.	University of Waterloo
"If a million people do a stupid thing, it's still a stupid thing." - Opus
Re: Destructor called too soon, Destructor not called - G++1.35
#327
Author: Gordon Joly
Date: Thu, 03 Aug 1989 13:24
416 lines
10844 bytes
Andrew,
Care to try this?
Gordon.

Surface mail: Dr. G.C.Joly, Department of Statistical Science,
      University College London, Gower Street, LONDON WC1E 6BT, U.K.
E-mail:                                            | Tel: +44 1 387 7050
 JANET (U.K. network) gordon@uk.ac.ucl.stats       |      extension 3636
 ARPA  gordon@stats.ucl.ac.uk[@nsfnet-relay.ac.uk] | FAX: +44 1 387 8057
 Relays: EAN: @ean-relay.ac.uk  UUCP: ...!uunet.uu.net!ucl-stats!gordon

-- < -- < -- < -- < -- < -- < -- < -- < -- < -- < -- < -- < -- < -- < -- 

# !/bin/sh
# This is a shell archive, shar, format file.
# To unarchive, feed this text into /bin/sh in the directory
# you wish the files to be in.

echo x - Makefile 1>&2
sed 's/^X//' > Makefile << 'End of Makefile'
X# to create & run "constructor/destructor" test for C++
X#
X# To run test, just utter "make" in this directory.
X#
X
X# filenames for errors
XEBC=errors-prob_bitwise_copying
XESEQ=errors-sequencing
X
XCC=g++				# use the GNU C++ compiler
X
Xtests:	testing_prog check.awk
X	testing_prog 2> $(EBC) > calling_sequence
X	if [ -s $(EBC) ]; then cat $(EBC); exit 1; else rm $(EBC); fi
X	# calling seq check is only valid if previous check was OK
X	awk -f check.awk calling_sequence > $(ESEQ)
X	if [ -s $(ESEQ) ]; then cat $(ESEQ); exit 1; else rm $(ESEQ); fi
X	# rm calling_sequence
X	echo " - Passed test OK"
X	
Xtesting_prog: x.h x.o testing_prog.o
X	$(CC) $(CFLAGS) -o testing_prog testing_prog.o x.o
X
Xtesting_prog.o: x.h testing_prog.cc
X	$(CC) $(CFLAGS) -c testing_prog.cc 2> /dev/null	# ignore warning msgs
X
Xx.o:	x.h x.cc
X	$(CC) $(CFLAGS) -c x.cc
X
Xclean:
X	rm -f *.o *..c core calling_sequence $(EBC) $(ESEQ)
X
Xclobber:	clean
X	rm -f testing_prog
End of Makefile
chmod 775 Makefile
echo x - README_local 1>&2
sed 's/^X//' > README_local << 'End of README_local'
XReceived: from cs.ucl.ac.uk by Stats.Ucl.AC.UK   via Satnet with SMTP
X           id aa02261; 29 Apr 88 16:39 BST
XTo: "Gordon Joly, Statistics, UCL" <gordon@uk.ac.ucl.stats>
Xcc: sam@uk.ac.ucl.cs
XSubject: Re: C++ test program 
XIn-reply-to: Your message of Thu, 28 Apr 88 16:45:44 +0100.
XDate: Fri, 29 Apr 88 16:36:24 +0100
XFrom: Paul Otto <otto@uk.ac.ucl.cs>
X
XThe main test I have is one which tests that constructors
X& destructors are correctly called.  If you have access, look
Xin /cs/research/2.5D/europa/otto/c++.bugs/ctor_dtor
Xat the READ_ME, Makefile & progs they refer to.  Should
Xbe reasonably painless to run the tests - but no C++ compiler
Xthat we've got passes them.  (Of course, the tests may be at
Xfault - but I don't think so - any checking is welcome.)
X
XIf you don't have access, let me know & I can mail them
X(or whatever).
X
XPaul
End of README_local
chmod 775 README_local
echo x - check.awk 1>&2
sed 's/^X//' > check.awk << 'End of check.awk'
X# Check output from ctor/dtor test prog.
X#
X# Input is assumed to be a sequence of lines of the form:
X#	<routine-name> called; "this" = <address>
X#	
X# An error is reported if, for any given address, the routine calls do not
X# occur as in the following BNF:
X#		{ ctor-call other-call* dtor-call }*
X# (Constructor call includes initializers.)
X#
X# NB This awk script is relatively fragile - it does not validate its
X# input, or do any other such checks for errors in the testing programs
X# themselves.
X#						GPO 16/11/87
X#	Minor mod (to tidy up prog slightly)	GPO 24/11/87
X
X	{	if (($1 == "x::x()") || ($1 == "x::x(x&)")){	# ctor
X			if (status[$5] == "defined"){
X				print "ERROR: multiple use of address " $5 " on line " NR
X			} else {
X				status[$5] = "defined"
X			}
X		} else if ($1 == "x::~x()"){			# dtor
X			if (status[$5] != "defined"){
X				print "ERROR: dtor called for unit'ed address " $5 " on line " NR
X			} else {
X				status[$5] = "undefined"
X			}
X		} else {					# other
X			if (status[$5] != "defined"){
X				print "ERROR: routine using unit'ed address " $5 " on line " NR
X			}
X		}
X	}
XEND	{	for (a in status){	# check that all dtors have been called
X			if (status[a] == "defined"){
X				print "ERROR: address " a " has not been dtor'ed by end of prog"
X			}
X		}
X	}
End of check.awk
chmod 775 check.awk
echo x - check.awk.bak 1>&2
sed 's/^X//' > check.awk.bak << 'End of check.awk.bak'
X# Check output from ctor/dtor test prog.
X#
X# Input is assumed to be a sequence of lines of the form:
X#	<routine-name> called; "this" = <address>
X#	
X# An error is reported if, for any given address, the routine calls do not
X# occur as in the following BNF:
X#		{ ctor-call other-call* dtor-call }*
X# (Constructor call includes initializers.)
X#
X# NB This awk script is relatively fragile - it does not validate its
X# input, or do any other such checks for errors in the testing programs
X# themselves.
X#						GPO 16/11/87
X
XBEGIN	{ nu = 0 }
X	{	if (($1 == "x::x()") || ($1 == "x::x(x&)")){	# ctor
X			if (status[$5] == "defined"){
X				print "ERROR: multiple use of address " $5 " on line " NR
X			} else {
X				status[$5] = "defined"
X			}
X		} else if ($1 == "x::~x()"){			# dtor
X			if (status[$5] != "defined"){
X				print "ERROR: dtor called for unit'ed address " $5 " on line " NR
X			} else {
X				status[$5] = "undefined"
X			}
X		} else {					# other
X			if (status[$5] != "defined"){
X				print "ERROR: routine using unit'ed address " $5 " on line " NR
X			}
X		}
X		used[nu++] = $5			# keep track of entries for end
X	}
XEND	{	for (i = 0; i < nu; i++){  # check that all dtors have been called
X			if (status[used[i]] == "defined"){
X				print "ERROR: address " used[i] " has not been dtor'ed by end of prog"
X				status[used[i]] = "reported"	# suppress further reports about this address
X			}
X		}
X	}
End of check.awk.bak
chmod 775 check.awk.bak
echo x - testing_prog.c 1>&2
sed 's/^X//' > testing_prog.c << 'End of testing_prog.c'
X#include "x.h"
X
X// first some routines to play with ...
X
Xx
Xf(x arg1, x arg2)
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xint
Xintf(x arg1, x arg2)
X{
X	x local1, local2, local3;
X
X	return 0;
X}
X
Xx
Xg()
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xx
Xh()
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xx
Xi(x arg)
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
X#ifndef pyr
Xx
Xdoubly_recursive(int depth_to_go)
X{
X	if (depth_to_go > 0){
X		return(f(doubly_recursive(depth_to_go-1),
X				doubly_recursive(depth_to_go-1)));
X	} else {
X		x local;
X		return(local);
X	}
X}
X#endif
X
X// Now call the routines & see what happens ...
Xint
Xmain()
X{
X	// test for calling of ctors & dtors on nested calls ...
X	{
X		x local;
X
X		local = f(g(),h());
X	}
X#ifndef pyr
X	// test for calling of ctors & dtors in recursive calls ...
X	doubly_recursive(3);
X#endif
X	// test for calling of ctors & dtors in nested calls occurring in
X	//  an expression
X	{
X		x a;
X		if (intf(i(g()),a))
X			7;
X	}
X	return 0;	// ought to return true status, but .....
X}
End of testing_prog.c
chmod 775 testing_prog.c
echo x - testing_prog.cc 1>&2
sed 's/^X//' > testing_prog.cc << 'End of testing_prog.cc'
X#include "x.h"
X
X// first some routines to play with ...
X
Xx
Xf(x arg1, x arg2)
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xint
Xintf(x arg1, x arg2)
X{
X	x local1, local2, local3;
X
X	return 0;
X}
X
Xx
Xg()
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xx
Xh()
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xx
Xi(x arg)
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
X#ifndef pyr
Xx
Xdoubly_recursive(int depth_to_go)
X{
X	if (depth_to_go > 0){
X		return(f(doubly_recursive(depth_to_go-1),
X				doubly_recursive(depth_to_go-1)));
X	} else {
X		x local;
X		return(local);
X	}
X}
X#endif
X
X// Now call the routines & see what happens ...
Xint
Xmain()
X{
X	// test for calling of ctors & dtors on nested calls ...
X	{
X		x local;
X
X		local = f(g(),h());
X	}
X#ifndef pyr
X	// test for calling of ctors & dtors in recursive calls ...
X	doubly_recursive(3);
X#endif
X	// test for calling of ctors & dtors in nested calls occurring in
X	//  an expression
X	{
X		x a;
X		if (intf(i(g()),a))
X			7;
X	}
X	return 0;	// ought to return true status, but .....
X}
End of testing_prog.cc
chmod 775 testing_prog.cc
echo x - x.cc 1>&2
sed 's/^X//' > x.cc << 'End of x.cc'
X// noddy class for testing purposes
X//
X// BEWARE: This file relies on being able to coerce a class pointer into
X// a long so that it can be printed.
X
X#include "x.h"
X#include <stream.h>
X
Xinline static void
Xtell_world(char * who, x* address)
X{
X	cout << who << " called; \"this\" = " << (long) address << "\n";
X	// Might be more convenient when debugging to use stderr, so that
X	//  stays in sync with error messages - but test makefile assumes
X	//  stdout.
X}
X
Xinline static void
Xerror_address_mismatch(char* routine, x* says, x* actual)
X{
X	cerr << "ERROR: address mismatch in call of " << routine
X		<< "; class instance thought address was " << (long) says
X		<< ", but it was actually " << (long) actual << "\n";
X}
X
Xx::x()
X{
X	tell_world("x::x()",this);
X	self = this;
X}
X
Xx::x(x& xref)
X{
X	tell_world("x::x(x&)",this);
X	self = this;
X	if (xref.self != &xref)
X		error_address_mismatch("x::x(x&)",xref.self,&xref);
X}
X
Xx&
Xx::operator=(x& rhs)
X{
X	tell_world("x::operator=(x&)",this);
X	if (rhs.self != &rhs)
X		error_address_mismatch("x::operator=(x&)",rhs.self,&rhs);
X	if (self != this)
X		error_address_mismatch("x::operator=(x&)",self,this);
X	return(*this);
X}
X
Xx::~x()
X{
X	tell_world("x::~x()",this);
X	if (self != this)
X		error_address_mismatch("x::~x()",self,this);
X}
End of x.cc
chmod 775 x.cc
echo x - x.h 1>&2
sed 's/^X//' > x.h << 'End of x.h'
X// simplest class which completely avoids bitwise copying.
X// good for testing calling of constructors and destructors.
X
Xclass x {
X	class x* self;	// Note own address for testing/debugging purposes
Xpublic:
X	x();
X	x(x&);
X	x& operator=(x&);
X	~x();
X};
End of x.h
chmod 775 x.h
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads