Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   destructor/design problem? (http://www.velocityreviews.com/forums/t267674-destructor-design-problem.html)

 Tino 06-24-2003 08:52 PM

destructor/design problem?

In the snippet below, if the problem line is present, my program
crashes during the Matrix operator*(const Matrix&) call. Would
someone point out to me why I'm having this problem?

Regards,
Ryan

#include <iostream>
#include <cmath>
#include <vector>
#include <exception>
#include <ctime>

using std::cout;
using std::cerr;
using std::endl;

class Matrix
{
private:
int m, n;
double *buffer;

public:
// Constructors
Matrix(int m_, int n_) : m(m_), n(n_), buffer(new double[m*n]){}
~Matrix()
{
if( buffer != NULL )
{
//delete []buffer; //<<<--- This is the problem line
}
}
Matrix& operator=(const Matrix&);
Matrix operator*(const Matrix&) const;
void fill_random();
};

Matrix& Matrix::operator=(const Matrix& A)
{
n = A.n;
m = A.m;

if( buffer != NULL ){
delete [] buffer;
buffer = NULL;
}

buffer = new double[m*n];
for(int i=0; i<n*m; i++)
buffer[i] = A.buffer[i];

return *this;
}

Matrix Matrix::operator*(const Matrix& A) const
{
Matrix C(m, A.n);
if(n == A.m)
for( int i=0; i<m; i++ )
for( int j=0; j<A.n; j++ )
for( int k=0; k<n; k++ )
C.buffer[i+j*C.m] += buffer[i+k*m]*buffer[k+j*C.m];
else
throw std::length_error("length_error exception in
Matrix::operator*(Matrix)");
return C;
}

void Matrix::fill_random()
{
long seed;
time(&seed);
srand(seed);
for( int i=0; i<m*n; ++i)
buffer[i] = double(rand()) / RAND_MAX;
}

int main()
{
int n = 3;

Matrix A(n,n);
Matrix B(n,n);
Matrix C(n,n);

try{
A.fill_random();
B.fill_random();
C = A * B;
}
catch( exception& e ){
std::cout << e.what() << std::endl;
}
catch(...){
std::cout << "Unknown exception" << std::endl;
}
return 0;
}

 Victor Bazarov 06-24-2003 09:13 PM

Re: destructor/design problem?

"Tino" <tino52@yahoo.com> wrote...
> In the snippet below, if the problem line is present, my program
> crashes during the Matrix operator*(const Matrix&) call. Would
> someone point out to me why I'm having this problem?

First of all let me note that you've not followed the "Rule of Three"
in your code. More details below.

>
> Regards,
> Ryan
>
> #include <iostream>
> #include <cmath>
> #include <vector>
> #include <exception>
> #include <ctime>
>
> using std::cout;
> using std::cerr;
> using std::endl;
>
> class Matrix
> {
> private:
> int m, n;
> double *buffer;
>
> public:
> // Constructors
> Matrix(int m_, int n_) : m(m_), n(n_), buffer(new double[m*n]){}

You simply _must_ define the copy c-tor if you have dynamic memory

Matrix(const Matrix& m_) : m(m_.m), n(m_.n),
buffer(new double[m*n])
{
std::copy(m_.buffer, m_.buffer + m*n, buffer);
}

> ~Matrix()
> {
> if( buffer != NULL )
> {
> //delete []buffer; //<<<--- This is the problem line

You're probably deleting it twice. The added copy-c-tor should
take care of that. Restore the delete:
delete[] buffer;

> }
> }
> Matrix& operator=(const Matrix&);
> Matrix operator*(const Matrix&) const;
> void fill_random();
> };
>
> Matrix& Matrix::operator=(const Matrix& A)
> {
> n = A.n;
> m = A.m;
>
> if( buffer != NULL ){
> delete [] buffer;
> buffer = NULL;
> }
>
> buffer = new double[m*n];
> for(int i=0; i<n*m; i++)
> buffer[i] = A.buffer[i];
>
> return *this;
> }
>
> Matrix Matrix::operator*(const Matrix& A) const
> {
> Matrix C(m, A.n);
> if(n == A.m)
> for( int i=0; i<m; i++ )
> for( int j=0; j<A.n; j++ )
> for( int k=0; k<n; k++ )
> C.buffer[i+j*C.m] += buffer[i+k*m]*buffer[k+j*C.m];
> else
> throw std::length_error("length_error exception in
> Matrix::operator*(Matrix)");
> return C;
> }
>
> void Matrix::fill_random()
> {
> long seed;
> time(&seed);
> srand(seed);
> for( int i=0; i<m*n; ++i)
> buffer[i] = double(rand()) / RAND_MAX;
> }
>
> int main()
> {
> int n = 3;
>
> Matrix A(n,n);
> Matrix B(n,n);
> Matrix C(n,n);
>
> try{
> A.fill_random();
> B.fill_random();
> C = A * B;
> }
> catch( exception& e ){
> std::cout << e.what() << std::endl;
> }
> catch(...){
> std::cout << "Unknown exception" << std::endl;
> }
> return 0;
> }

HTH

Victor

 Ivan Vecerina 06-24-2003 09:17 PM

Re: destructor/design problem?

"Tino" <tino52@yahoo.com> wrote in message
> In the snippet below, if the problem line is present, my program
> crashes during the Matrix operator*(const Matrix&) call. Would
> someone point out to me why I'm having this problem?

I haven't checked everything in detail, but your class
lacks a copy-constructor:
Matrix( Matrix const& orig );
(implementation shall be similar to the assignment op,
except that there are no previous contents to destroy).

> ~Matrix()
> {
> if( buffer != NULL )
> {
> //delete []buffer; //<<<--- This is the problem line
> }
> }

NB: the test for NULL above is redundant:
delete[] NULL; is required to be a no-op.

> Matrix& Matrix::operator=(const Matrix& A)
> {
> n = A.n;
> m = A.m;
>
> if( buffer != NULL ){
> delete [] buffer;
> buffer = NULL;
> }

NB: this assignment operator is unsafe in case of
self-assignment, and also isn't exception-safe.
The best way to solve both problems is to
allocate the new buffer first, copy the
contents, then release the old buffer.

hth,
--
Ivan Vecerina, Dr. med. <> http://www.post1.com/~ivec
Soft Dev Manger, XiTact <> http://www.xitact.com
Brainbench MVP for C++ <> http://www.brainbench.com

 All times are GMT. The time now is 10:09 AM.