tom@ssd.csd.harris.com (Tom Horsley) (11/02/90)
Given a class that looks like: class someclass { public: someclass(someclass& arg); ... } Is it ever possible with a correctly functioning C++ compiler for your program to reach the body of the if statement in the following copy constructor: someclass::someclass(someclass& arg) { if (this == &arg) { // Can I get here? } } In other words can a copy constructor ever be called with a reference to self as its argument? I hope the answer is 'NO' since all the C++ books emphasize that constructors only get raw bits and it is their job to initialize those bits. So if '*this' is raw bits and 'arg' is a reference to an already existing class, how can they be located at the same point in memory? I spent several hours last night determining that this is actually happening in a Turbo C++ program I wrote in which I have overloaded a lot of arithmetic operators and have written some complex expressions involving these overloaded operators. When I modified my constructors to detect this case and avoid clobbering the information it is about to copy, the program started working flawlessly (it worked on two different g++ implementations before I tried it on Turbo C++). Does this look as much like a bug to everyone else as it does to me, or have I possibly encountered one of those subtle gotcha's that always seem to attract programmers who are just starting to use a new language? -- ====================================================================== domain: tahorsley@csd.harris.com USMail: Tom Horsley uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle Delray Beach, FL 33444 +==== Censorship is the only form of Obscenity ======================+ | (Wait, I forgot government tobacco subsidies...) | +====================================================================+
jbuck@galileo.berkeley.edu (Joe Buck) (11/03/90)
In article <TOM.90Nov2072213@hcx2.ssd.csd.harris.com>, tom@ssd.csd.harris.com (Tom Horsley) writes: |> Is it ever possible with a correctly functioning C++ compiler for your |> program to reach the body of the if statement in the following copy |> constructor: |> |> someclass::someclass(someclass& arg) |> { |> if (this == &arg) { |> // Can I get here? |> } |> } |> |> In other words can a copy constructor ever be called with a reference to |> self as its argument? What's probably happened is that your program has a memory allocation bug. Specifically, you've deleted an object but you still have a pointer to it lying around, so you're trying to use an object that you have deleted. Neophytes always think they've found a compiler bug when this bites them. |> I spent several hours last night determining that this is actually happening |> in a Turbo C++ program I wrote in which I have overloaded a lot of |> arithmetic operators and have written some complex expressions involving |> these overloaded operators. When I modified my constructors to detect this |> case and avoid clobbering the information it is about to copy, the program |> started working flawlessly (it worked on two different g++ implementations |> before I tried it on Turbo C++). You either have a bug in your memory allocation somewhere that didn't bite you under g++ for some reason, or there's a bug in one of the Turbo C++ classes that you are using. -- Joe Buck jbuck@galileo.berkeley.edu {uunet,ucbvax}!galileo.berkeley.edu!jbuck
tom@ssd.csd.harris.com (Tom Horsley) (11/03/90)
>What's probably happened is that your program has a memory allocation bug. >Specifically, you've deleted an object but you still have a pointer to >it lying around, so you're trying to use an object that you have deleted. >Neophytes always think they've found a compiler bug when this bites them. Yep. I would agree that this is a very likely thing to happen except for the fact that all my class instances are 'auto' storage class, I am not using new or delete (to create classes) anywhere. The more I look at it, the more it looks like Turbo C++ is re-using one of the temps it created for evaluation of the expression (involving overloaded operators) before the lifetime of that temp actually expired. -- ====================================================================== domain: tahorsley@csd.harris.com USMail: Tom Horsley uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle Delray Beach, FL 33444 +==== Censorship is the only form of Obscenity ======================+ | (Wait, I forgot government tobacco subsidies...) | +====================================================================+
vaughan@mcc.com (Paul Vaughan) (11/04/90)
From: tom@ssd.csd.harris.com (Tom Horsley) Given a class that looks like: class someclass { public: someclass(someclass& arg); ... } Is it ever possible with a correctly functioning C++ compiler for your program to reach the body of the if statement in the following copy constructor: someclass::someclass(someclass& arg) { if (this == &arg) { // Can I get here? } } Yes and No. I agree with you that it generally shouldn't happen, but here is a case where it can. #include <stream.h> class A { public: A() {} A(A& a) { if( this == &a) cout << "copying myself\n"; } }; main() { A* a1 = new A; delete a1; A* a2 = new A(*a1); // <= using a dead object here } Both g++ and sun cfront 2.0 print "copying myself" on this one, but that has more to do with the malloc/free package than anything else. The various compilers differ in the details of when temporary objects created as arguments in expressions get deleted. This might account for why it works differently under different compilers. Also, note that constructors don't exactly get raw bits--all members have been constructed and the constructor initialization list has been run before the constructor body is run. But, basically, a copy constructor should never find itself copying itself. Paul Vaughan, MCC CAD Program | ARPA: vaughan@mcc.com | Phone: [512] 338-3639 Box 200195, Austin, TX 78720 | UUCP: ...!cs.utexas.edu!milano!cadillac!vaughan
BMS101@psuvm.psu.edu (11/09/90)
I A COMING IN IN THE MIDDLE OF THIS THREAD BUT IF IT HASN'T BEEN SAID ALREADY TURBO C++ DOES HAVE MEMORY ALLOCATION BUGS THAT CAN BE CORRECTED BY CALLING BORLAND AND D/L'ING THEIR BUG FIXES.