我很困惑,因为我现在花了3天时间解决这个问题,试图弄清楚我做错了什么,但我真的不知道,所以任何提示或建议都不仅仅是值得赞赏的。基本上,我必须使用引用计数做矩阵类,并且程序运行良好,但在测试它时我意识到出现了问题。例如,我在main中写道:
matrix a(5,5,4); // - 5x5 matrix filled with 4
matrix b(3,3,2); // 3x3 matrix filled with 3
matrix c=b; // copy constructor used here
a=b;
现在当我更改矩阵c中的值时,例如:
c(2,2)=1;
我预计矩阵b的参考计数器将减少1,程序将创建矩阵c 3x3,填充2但位置为1(2,2)。 我不知道为什么但程序会在所有矩阵中更改此值,并且因为我在valgrind中有一些内存泄漏。伙计们,你能告诉我,我做错了吗?
下面我附上所有重要的声明和valgrind错误。
#ifndef __CREFMATIRX_H__
#define __CREFMATRIX_H__
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class matrix
{
private:
class rcmatrix;
rcmatrix *data;
public:
class Cref;
class Size_Check{};
matrix();
~matrix();
matrix(const matrix &m);
matrix(const int rows, const int cols, const double num);
matrix(const int rows, const int cols, double **arg_mat);
void check(const int i, const int j)const;
double read(int i, int j)const;
void write(const int i, const int j, const double num);
matrix & operator =(const matrix &m);
Cref operator ()(const int i, const int j);
friend ostream& operator<<(ostream &s, const matrix &m);
};
class matrix::rcmatrix
{
private:
rcmatrix(const rcmatrix&);
rcmatrix &operator =(const rcmatrix&);
public:
int rows; //number of rows
int cols; // number of columns
double **mat; //pointer to matrix
int n; //reference counter
~rcmatrix()
{
for(int i=0;i<rows;i++)
delete []mat[i];
delete []mat;
}
rcmatrix(const int r, const int c, const double num)
{
n=1;
rows=r;
cols=c;
mat= new double *[rows];
for(int i=0;i<rows;i++)
mat[i]=new double[cols];
for(int k=0;k<rows;k++)
{
for(int j=0;j<cols;j++)
mat[k][j]=num;
}
}
rcmatrix(const int r, const int c, double **arg_mat)
{
n=1;
rows=r;
cols=c;
mat=new double *[rows];
for(int i=0; i<rows; i++)
mat[i]=new double [cols];
for(int j=0;j<rows;j++)
{
for(int k=0;k<cols;k++)
mat[j][k]=arg_mat[j][k];
}
mat=arg_mat;
}
rcmatrix* detach() //checking value of reference counter
{
if(n==1)
return this;
rcmatrix *t= new rcmatrix(rows,cols,mat);
n--;
return t;
}
};
class matrix::Cref
{
friend class matrix;
matrix &m;
int i,j;
Cref(matrix &mm, const int ii, const int jj): m(mm),i(ii),j(jj){};
public:
operator double()const
{
return m.read(i,j);
}
matrix::Cref& operator = (double c)
{
m.write(i,j,c);
return *this;
}
matrix::Cref& operator = (const Cref& ref)
{
return operator= ((double)ref);
}
};
matrix::matrix()
{
data=new rcmatrix(0,0,0.0);
}
matrix::matrix(const matrix &m)
{
m.data->n++;
data=m.data;
}
matrix::~matrix()
{
if(--data->n==0) //line 138
delete data;
}
matrix::matrix(const int r, const int c, const double n)
{
data=new rcmatrix(r,c,n);
}
matrix::matrix(const int r, const int c, double **arg_mat)
{
data= new rcmatrix(r,c,arg_mat);
}
matrix& matrix::operator =(const matrix &m)
{
m.data->n++;
if(--data->n==0)
delete data;
data=m.data;
return *this;
}
inline void matrix::check(const int i, const int j)const
{
if(data->rows<i||data->cols<j)
throw Size_Check();
}
inline double matrix::read( int i, int j)const
{
return data->mat[i][j];
}
inline void matrix::write( int i, int j,const double num)
{
data=data->detach();
data->mat[i][j]=num;
}
matrix::Cref matrix::operator ()(const int i, const int j)
{
check(i,j);
return Cref(*this,i,j);
}
ostream & operator <<(ostream &s, const matrix &m)
{
for(int r=0; r<m.data->rows;r++)
{
for(int c=0; c<m.data->cols;c++)
s<<m.data->mat[r][c]<<" ";
s<<endl;
}
return s;
}
#endif /* __RCMATRIX__H__ */
Valgrind错误:
==2393== Invalid read of size 4
==2393== at 0x8048E31: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:50)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D4E: main (crefmatrix.cpp:14)
==2393== Address 0x43f6cd8 is 0 bytes inside a block of size 12 free'd
==2393== at 0x402ECB8: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048E71: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:51)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D30: main (crefmatrix.cpp:16)
==2393== Block was alloc'd at
==2393== at 0x402DDAC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048EC4: matrix::rcmatrix::rcmatrix(int, int, double) (rcmatrix.h:60)
==2393== by 0x8048A6D: matrix::matrix(int, int, double) (rcmatrix.h:143)
==2393== by 0x8048C6C: main (crefmatrix.cpp:15)
==2393==
==2393== Invalid read of size 4
==2393== at 0x8048E45: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:50)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D4E: main (crefmatrix.cpp:14)
==2393== Address 0x43f6cd8 is 0 bytes inside a block of size 12 free'd
==2393== at 0x402ECB8: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048E71: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:51)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D30: main (crefmatrix.cpp:16)
==2393== Block was alloc'd at
==2393== at 0x402DDAC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048EC4: matrix::rcmatrix::rcmatrix(int, int, double) (rcmatrix.h:60)
==2393== by 0x8048A6D: matrix::matrix(int, int, double) (rcmatrix.h:143)
==2393== by 0x8048C6C: main (crefmatrix.cpp:15)
==2393==
==2393== Invalid free() / delete / delete[] / realloc()
==2393== at 0x402ECB8: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048E4F: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:50)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D4E: main (crefmatrix.cpp:14)
==2393== Address 0x43f6d18 is 0 bytes inside a block of size 24 free'd
==2393== at 0x402ECB8: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048E4F: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:50)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D30: main (crefmatrix.cpp:16)
==2393== Block was alloc'd at
==2393== at 0x402DDAC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048F0F: matrix::rcmatrix::rcmatrix(int, int, double) (rcmatrix.h:62)
==2393== by 0x8048A6D: matrix::matrix(int, int, double) (rcmatrix.h:143)
==2393== by 0x8048C6C: main (crefmatrix.cpp:15)
==2393==
==2393== Invalid free() / delete / delete[] / realloc()
==2393== at 0x402ECB8: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048E71: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:51)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D4E: main (crefmatrix.cpp:14)
==2393== Address 0x43f6cd8 is 0 bytes inside a block of size 12 free'd
==2393== at 0x402ECB8: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048E71: matrix::rcmatrix::~rcmatrix() (rcmatrix.h:51)
==2393== by 0x8048A20: matrix::~matrix() (rcmatrix.h:138)
==2393== by 0x8048D30: main (crefmatrix.cpp:16)
==2393== Block was alloc'd at
==2393== at 0x402DDAC: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2393== by 0x8048EC4: matrix::rcmatrix::rcmatrix(int, int, double) (rcmatrix.h:60)
==2393== by 0x8048A6D: matrix::matrix(int, int, double) (rcmatrix.h:143)
==2393== by 0x8048C6C: main (crefmatrix.cpp:15)
==2393==
==2393==
==2393== HEAP SUMMARY:
==2393== in use at exit: 19,028 bytes in 5 blocks
==2393== total heap usage: 19 allocs, 18 frees, 20,404 bytes allocated
==2393==
==2393== LEAK SUMMARY:
==2393== definitely lost: 12 bytes in 1 blocks
==2393== indirectly lost: 72 bytes in 3 blocks
==2393== possibly lost: 0 bytes in 0 blocks
==2393== still reachable: 18,944 bytes in 1 blocks
==2393== suppressed: 0 bytes in 0 blocks
答案 0 :(得分:0)
一个明显的问题是rcmatrix
的构造函数,如果引用计数不完全为1,则detach()
函数中使用该构造函数。
rcmatrix(const int r, const int c, double **arg_mat)
{
n=1;
rows=r;
cols=c;
mat=new double *[rows];
for(int i=0; i<rows; i++)
mat[i]=new double [cols];
for(int j=0;j<rows;j++)
{
for(int k=0;k<cols;k++)
mat[j][k]=arg_mat[j][k];
}
mat=arg_mat;
}
此构造函数应创建由另一个arg_mat
管理的现有rcmatrix
的新独立副本。但是,在最后一行中指定
mat=arg_mat;
这实质上导致了两个问题。
arg_mat
现在与新rcmatrix
共享(您观察到分配给c(2,2)的值会写入所有矩阵)。行中所述构造函数中分配的内存
mat=new double *[rows];
for(int i=0; i<rows; i++)
mat[i]=new double [cols];
失去了(valgrind)。
我不知道这些是您代码中的唯一问题。我想把支票留给你。