destructor trouble when using overloaded + operator

I

itdevries

Hi,
I've ran into some trouble with an overloaded + operator, maybe
someone can give me some hints what to look out for.

I've got my own custom vector class, as a part of that I've overloaded
the + operator by means of a friend function. Everything worked fine
until I decided to use a variable array size (by using new/delete),
now I get an error when a temporary object is deleted (e.g. after
addition), the error occurs at the delete statement in the destructor,
I can see that the object isn't initialized... the error I get is
something like "debug assertion failed".

any things to look out for?
thanks...
I
 
K

Kai-Uwe Bux

itdevries said:
Hi,
I've ran into some trouble with an overloaded + operator, maybe
someone can give me some hints what to look out for.

I've got my own custom vector class, as a part of that I've overloaded
the + operator by means of a friend function. Everything worked fine
until I decided to use a variable array size (by using new/delete),
now I get an error when a temporary object is deleted (e.g. after
addition), the error occurs at the delete statement in the destructor,
I can see that the object isn't initialized... the error I get is
something like "debug assertion failed".

any things to look out for?

a) Post code. As of now, we do not even know whether + is used to denote
concatenation or member-wise addition (just to name the most common).

b) A delete statement in the destructor is weird. The destructor should be
empty (as far as I can see; but then again: post code). Similarly, variable
array sizes with a vector class are handled not via new/delete, but by the
vector itself. See std::vector for an example.


Best

Kai-Uwe Bux
 
I

Ian Collins

itdevries said:
Hi,
I've ran into some trouble with an overloaded + operator, maybe
someone can give me some hints what to look out for.

I've got my own custom vector class, as a part of that I've overloaded
the + operator by means of a friend function. Everything worked fine
until I decided to use a variable array size (by using new/delete),
now I get an error when a temporary object is deleted (e.g. after
addition), the error occurs at the delete statement in the destructor,
I can see that the object isn't initialized... the error I get is
something like "debug assertion failed".
If you want constructive help, post the shortest compilable code that
shows your problem.
 
I

itdevries

a) Post code. As of now, we do not even know whether + is used to denote
concatenation or member-wise addition (just to name the most common).

b) A delete statement in the destructor is weird. The destructor should be
empty (as far as I can see; but then again: post code). Similarly, variable
array sizes with a vector class are handled not via new/delete, but by the
vector itself. See std::vector for an example.

Best

Kai-Uwe Bux

ok, I'll try to keep it shor:

// header:
friend vec3 operator+(const vec3& vecA, const vec3& vecB);
private:
float* m_coord;

//______________________________________
// constructor:
vec3::vec3(const int& len){
m_len = len;
m_coord = new float[m_len];
}


//______________________________________
// destructor:
vec3::~vec3(void){
delete [] this->m_coord;
}

// error at this statement:
Rd0 = Rd0 + Atotal * vec;

// Rd0, are vectors of the vec3 class, Atotal is a matrix (I've also
defined multiplication of matrix x vector in another class)

thanks, IdV
 
K

Kai-Uwe Bux

itdevries said:
ok, I'll try to keep it shor:

Informative is better than short. The FAQ advises to post a minimal but
compilable example of code that exhibits the problem.

// header:
friend vec3 operator+(const vec3& vecA, const vec3& vecB);
private:
float* m_coord;

//______________________________________
// constructor:
vec3::vec3(const int& len){
m_len = len;
m_coord = new float[m_len];
}


//______________________________________
// destructor:
vec3::~vec3(void){
delete [] this->m_coord;
}

// error at this statement:
Rd0 = Rd0 + Atotal * vec;

// Rd0, are vectors of the vec3 class, Atotal is a matrix (I've also
defined multiplication of matrix x vector in another class)

One thing that comes to mind is the assignment operator. Since you have a
pointer member, copy-constructor, assignment, and destructor need some
care. That is one thing to watch out for since you have an error on
something that is related to self-assignment.

The operator+ looks as follows, I presume:

vec3 operator+ (const vec3& vecA, const vec3& vecB) {
assert( vecA.m_len == vecB.m_len );
vec3 result ( vecA );
for ( vec3::size_type i = 0; i < vecA.m_len; ++i ) {
result.m_coord += vecB.m_coord;
}
return ( result );
}

So, if you have vectors of different dimensions, addition would be
ill-defined. I mention that because you suggested that you ran into
troubles when you started with variable sizes.


Best

Kai-Uwe Bux
 
I

itdevries

ok, I'll try to keep it shor:

Informative is better than short. The FAQ advises to post a minimal but
compilable example of code that exhibits the problem.




// header:
friend vec3 operator+(const vec3& vecA, const vec3& vecB);
private:
float* m_coord;
//______________________________________
// constructor:
vec3::vec3(const int& len){
m_len         = len;
m_coord               = new float[m_len];
}
//______________________________________
// destructor:
vec3::~vec3(void){
delete [] this->m_coord;
}
// error at this statement:
Rd0           = Rd0 + Atotal * vec;
// Rd0, are vectors of the vec3 class, Atotal is a matrix (I've also
defined multiplication of matrix x vector in another class)

One thing that comes to mind is the assignment operator. Since you have a
pointer member, copy-constructor, assignment, and destructor need some
care. That is one thing to watch out for since you have an error on
something that is related to self-assignment.

The operator+ looks as follows, I presume:

  vec3 operator+ (const vec3& vecA, const vec3& vecB) {
    assert( vecA.m_len == vecB.m_len );
    vec3 result ( vecA );
    for ( vec3::size_type i = 0; i < vecA.m_len; ++i ) {
      result.m_coord += vecB.m_coord;
    }
    return ( result );
  }

So, if you have vectors of different dimensions, addition would be
ill-defined. I mention that because you suggested that you ran into
troubles when you started with variable sizes.

Best

Kai-Uwe Bux- Tekst uit oorspronkelijk bericht niet weergeven -

- Tekst uit oorspronkelijk bericht weergeven -- Tekst uit oorspronkelijk bericht niet weergeven -

- Tekst uit oorspronkelijk bericht weergeven -


Kai-Uwe, thanks for your response...

the addition code looks like this:

// _______________________________________________________
vec3 operator+(const vec3& vecA, const vec3& vecB){

vec3 result(vecA.m_len);

for (int ii=0;ii<result.m_len;ii++){
result(ii) = vecA(ii) + vecB(ii);
}
return result;
}

mat*vec multiplication is defined in the mat3 (not vec3) class as:

// _____________________________________________________
//
// matrix * vector
//
vec3 operator*(const mat3& mat, const vec3& vec){

vec3 result(vec.m_len);

for (int rr=0;rr<3;rr++){
for (int cc=0;cc<3;cc++){
result(rr) += mat(rr,cc) * vec(cc);
} // for cc
} // for rr

return result;

} // operator*



I'm aware that I haven't checked for same length (and have assumed
that the vector is a column vector) but that's ok at this point; I
_know_ the vectors are the same length and should be columns and I'm
not trying to create a robust general purpose library, I may add error
checking later.

Note that I've also overloaded the () operators to allow for row,
column style indexing in matrices (and vectors for syntax symmetry
between vec3 and mat3 reasons) and using the [] syntax with double
indexing is a bit of a bitch.

Now through debugging it seems that I'm trying to delete an object
which has already been deleted, not entirely sure how it's happening
but it seems to be the case, maybe you have any ideas?
Igor
 
I

itdevries

ok, I'll try to keep it shor:
// header:
friend vec3 operator+(const vec3& vecA, const vec3& vecB);
private:
float* m_coord;
//______________________________________
// constructor:
vec3::vec3(const int& len){
m_len              = len;
m_coord            = new float[m_len];
}
//______________________________________
// destructor:
vec3::~vec3(void){
delete [] this->m_coord;
}
// error at this statement:
Rd0                = Rd0 + Atotal * vec;
// Rd0, are vectors of the vec3 class, Atotal is a matrix (I've also
defined multiplication of matrix x vector in another class)
thanks, IdV

It is hard to say for certain since you have not posted compilable code,
but I would guess that you are having trouble stemming from the fact
that you have not defined a copy constructor or assignment operator.

When the temporary vec3 is copied to Rd0, it's m_coord pointer is
copied.  Then the temporary is destructed leaving Rd0 with an invalid
pointer.  Then Rd0 is eventually destructed and attempts to delete an
invalid pointer.  This is all conjecture of course.

In general, if you design a class that needs a destructor, then it will
almost always need a copy constructor and assignment operator as well,
exactly because of the problem you seem to be encountering.

The easiest way to fix your program would be make m_coord a
std::vector<float> instead of using new/delete to manage memory
yourself.  std::vector already correctly implements copy construction
and assignment.

Finally, a code example that may more clearly demonstratethe problem
that I think you are seeing.  How many times is new called?  How many
times is delete called?

#include <iostream>

class bad
{
public:
     bad()
     {
         m_p = new int[5];
         std::cout << "new:    " << m_p << std::endl;
     }

     ~bad()
     {
         std::cout << "delete: " << m_p << std::endl;
         delete [] m_p;
     }
private:
     int * m_p;

};

int main()
{
     bad b1;
     bad b2(b1);
     return 0;

}

Alan, thanks very much, you are right, that was the error. I'm aware
of the standard vector class but I've got some reasons for not using
it.
thanks very much!
Igor
 
J

Junchen WANG

a) Post code. As of now, we do not even know whether + is used to denote
concatenation or member-wise addition (just to name the most common).
b) A delete statement in the destructor is weird. The destructor should be
empty (as far as I can see; but then again: post code). Similarly, variable
array sizes with a vector class are handled not via new/delete, but by the
vector itself. See std::vector for an example.

Kai-Uwe Bux

ok, I'll try to keep it shor:

// header:
friend vec3 operator+(const vec3& vecA, const vec3& vecB);
private:
float* m_coord;

//______________________________________
// constructor:
vec3::vec3(const int& len){
m_len = len;
m_coord = new float[m_len];

}

//______________________________________
// destructor:
vec3::~vec3(void){
delete [] this->m_coord;

}

// error at this statement:
Rd0 = Rd0 + Atotal * vec;

// Rd0, are vectors of the vec3 class, Atotal is a matrix (I've also
defined multiplication of matrix x vector in another class)

thanks, IdV- Òþ²Ø±»ÒýÓÃÎÄ×Ö -

- ÏÔʾÒýÓõÄÎÄ×Ö -

it seems that the problem was related to shallow copy or array
overflow.
Please refine the copy ctor and assignment operator
 
A

anon

itdevries wrote:
[....]


Your "example" doesn't have main(), classes declaration and
implementation, therefore it is not compilable example.
 
T

terminator

I shoud qout:
****
One thing that comes to mind is the assignment operator. Since you have a
pointer member, copy-constructor, assignment, and destructor need some
care.
****

regards,
FM.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top