Destructor being called early...
I'm putting together a custom math package with things like 3d-vectors, complex numbers, and matrices. In doing so I'm overriding the basic operators: &operator=(), &operator+(), etc.
Everything seems to work OK, except for the matrices. I stepped through with a debugger, and the underlying operations themselves work fine, for example:
Vector3D v1,v2,v3;
v3=v1+v2 //works fine
Matrix m1(2,2),m2(2,2),m3(2,2); //parameters are matrix dimensions
m3=m2; //works fine
m1+m2; //works fine
m3=m1+m2; //crashes
The debugger indicates that the return value of m1+m2 gets automatically run through the destructor before getting passed to the &operator=().
Here's my relevant function prototypes:
Matrix(int rows,int columns);
~Matrix();
Matrix &operator=(const Matrix &right);
Matrix operator+(const Matrix &right);
//as compared to:
Vector3D();
~Vector3D();
Vector3D &operator=(const Vector3D &right);
Vector3D operator+(const Vector3D &right);
Any ideas?
[1158 byte] By [
jefranki] at [2007-11-18 19:07:29]

# 1 Re: Destructor being called early...
can you post the code for Matrix copy constructor, and operator+ ?
Guysl at 2007-11-9 0:32:11 >

# 2 Re: Destructor being called early...
I take it you really meant the assignment operator, not the copy constructor (the copy constructor is fairly lengthy).
Attached is a code "snippet"; the class is fairly complex, so this amounts to 170 lines...I thought you'd prefer to open it as a separate file. I did what I could to add comments, but since it's a personal project, comments were kind of sparse beforehand.
I have a feeling the problem might have to do with some sort compiler setting or something, but I don't know enough about compiler functionality to say for sure.
Anyway, given code to the effect of:
Matrix A(2,2), B(2,2), C(2,2);
C=A+B;
my debugger seems to indicate that the program flow of the offending code seems to be something to the effect of (in psuedocode):
execute "add A and B"
{
Matrix Sum;
...
do operations to evalute Sum
...
return Sum;
}
automatically Call destructor on Sum
try to execute C=Sum
but wait, Sum was destroyed:
CRASH!!!
With all my similar classes, the destructor for Sum is not called until after the whole line of code "C=A+B;" finishes executing.
Keep in mind that the program does not crash for C=B; or A+B;
Btw, I'm using Codewarrior 8. I'll be greatful for any ideas.
# 3 Re: Destructor being called early...
You better post your entire code, since the destructor will also be called. You claim that everything is fine, but you are doing an awful lot of dynamic allocation, and you may have a bug you never realized. Also, it is difficult for anyone here to diagnose a problem by just looking at code -- your problem can be solved much easier if we can just compile and run it.
For some reason, your code seems overly complex for something as simple as deleting all the matrix memory and just assigning new memory and copying. Also, why the redundant usage of (*this)? You are already in the object, so you don't need to use (*this).
Regards,
Paul McKenzie
# 4 Re: Destructor being called early...
No, I meant copy constructor and it seems I knew why...
you have no copy constructor for matrix which contains
pointers, therefore when you return a matrix by using the
default copy constructor - you use a temporary object
that invokes the destructor and then the pointers get freed.
you should implement a copy constructor for your matrix.
Guysl at 2007-11-9 0:35:20 >

# 5 Re: Destructor being called early...
Yes, it's called the "rule of three". If you implement an assignment operator, you need a copy constructor and destructor.
Also to add to Guysl's words, it makes no sense to be able to do this:
Matrix a;
Matric b;
b = a;
And not be able to do this:
Matrix a;
Matrix b = a;
Without a copy constructor, you can't do the latter safely.
Regards,
Paul McKenzie
# 6 Re: Destructor being called early...
jefranki posted:
I take it you really meant the assignment operator, not the copy constructor (the copy constructor is fairly lengthy).
my last post refered the source snippets that you had supplied,
which missed a copy constructor. if you have a "fairy lengthy"
copy constructor, then please post it.
Guysl at 2007-11-9 0:37:24 >

# 7 Re: Destructor being called early...
Originally posted by jefranki
I take it you really meant the assignment operator, not the copy constructor (the copy constructor is fairly lengthy).The copy constructor should be virtually the same as the assignment operator. As a matter of fact, the only difference that I would see is that the assignment operator checks for self-assignment and does a return *this:
class Matrix
{
public:
Matrix(const Matrix& rhs)
{
// Initialize basic members (maybe set pointers to NULL and vars to initial values)
// now call common "copy" function
SetEqual( rhs );
}
Matrix& operator = (const Matrix& rhs)
{
// test for self-assignment
if ( this != &rhs )
// call common copy function
SetEqual( rhs );
return *this;
}
protected:
void SetEqual(const Matrix& rhs)
{
// code to copy rhs to *this
}
};
Does your code look like this, or is your assignment operator radically different than your copy constructor (which would raise a a few eyebrows as to how you've implemented things).
Regards,
Paul McKenzie
# 8 Re: Destructor being called early...
a question to Paul:
I've seen before the usage of: 'if ( this != &rhs )' in operator= and I wonder is this form is better than:
'if (*this == rhs)' when operator== is implemented.
when two objects have the same data, it seems to me a waste
to delete old data and replace it with the same data, even
if these objects are allocated in different addresses.
Regards,
Guy
Guysl at 2007-11-9 0:39:25 >

# 9 Re: Destructor being called early...
Originally posted by Guysl
a question to Paul:
I've seen before the usage of: 'if ( this != &rhs )' in operator= and I wonder is this form is better than:
'if (*this == rhs)' when operator== is implemented.
when two objects have the same data, it seems to me a waste
to delete old data and replace it with the same data, even
if these objects are allocated in different addresses.
Regards,
Guy Yes, there is more than one way to do the test for self-assignment, and admittedly, yours is a better check. It actually checks for the same data more thoroughly than just a pointer comparison (provided that operator == has been coded for the class).
Regards,
Paul McKenzie
# 10 Re: Destructor being called early...
Everyone,
Thanks...adding a real copy constructor fixed it. I previously had something like a copy constructor that used a pointer instead the "const Matrix &rhs".
I now remember why I tried to do it that way...to use the index operators, three data members of a Matrix have to get altered...can't do that if it's const. That was about a year ago and before I thought of typecasting things to a non-const pointer. (That's the last time a take a year off from a half-complete project!)
I also didn't previously know that a copy constructor is automatically used with a return parameter. All my OOP training is either from a C++ book, or from my required Java courses (a.k.a. "sloppy programming") at my university.
Everything now executes! I now just gotta check to make sure I did all my math right and that it catches all bad input (which is still a lot of work to go). I'll post my whole package when that's complete. Thanks again!
