我编写一个简单的程序,将复杂函数(z,exp(z),...)应用于pgm图像并返回结果。该计划正在运作,并做它应该做的事情。但是,有11个内存泄漏,我无法解决。我的猜测是麻烦在于矩阵模板容器I代码及其构造函数和析构函数。 要调试我正在使用valgrind并且该程序是用c ++编写的。
运行valgrind的结果如下:
==7690== Memcheck, a memory error detector
==7690== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7690== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7690== Command: ./tp0 -i f14.pgm -f z -o ff14.pgm
==7690==
==7690==
==7690== HEAP SUMMARY:
==7690== in use at exit: 160 bytes in 11 blocks
==7690== total heap usage: 45 allocs, 34 frees, 18,357 bytes allocated
==7690==
==7690== 8 bytes in 1 blocks are still reachable in loss record 1 of 11
==7690== at 0x4C298A0: operator new[](unsigned long) (vg_replace_malloc.c:389)
==7690== by 0x404871: Matrix<Pixel>::Matrix(unsigned int, unsigned int) (matrix.hpp:44)
==7690== by 0x404471: PGMImage::PGMImage(unsigned int, unsigned int) (pgm_image.cpp:14)
==7690== by 0x405475: PGMParser::set_pgm_dimensions(std::vector<int, std::allocator<int> >) (pgm_parser.cpp:147)
==7690== by 0x4050CD: PGMParser::get_pgm() (pgm_parser.cpp:94)
==7690== by 0x404D67: PGMParser::PGMParser(std::string const&) (pgm_parser.cpp:25)
==7690== by 0x404212: main (main.cpp:52)
==7690==
==7690== 8 bytes in 1 blocks are still reachable in loss record 2 of 11
==7690== at 0x4C298A0: operator new[](unsigned long) (vg_replace_malloc.c:389)
==7690== by 0x403703: Matrix<Complex>::Matrix(unsigned int, unsigned int) (matrix.hpp:44)
==7690== by 0x4024A5: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:49)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== 8 bytes in 1 blocks are still reachable in loss record 3 of 11
==7690== at 0x4C298A0: operator new[](unsigned long) (vg_replace_malloc.c:389)
==7690== by 0x4049C9: Matrix<Pixel>::Matrix(Matrix<Pixel> const&) (matrix.hpp:56)
==7690== by 0x404579: PGMImage::PGMImage(PGMImage const&) (pgm_image.cpp:31)
==7690== by 0x4024DD: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:57)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== 12 bytes in 1 blocks are still reachable in loss record 4 of 11
==7690== at 0x4C298A0: operator new[](unsigned long) (vg_replace_malloc.c:389)
==7690== by 0x4048B4: Matrix<Pixel>::Matrix(unsigned int, unsigned int) (matrix.hpp:46)
==7690== by 0x404471: PGMImage::PGMImage(unsigned int, unsigned int) (pgm_image.cpp:14)
==7690== by 0x405475: PGMParser::set_pgm_dimensions(std::vector<int, std::allocator<int> >) (pgm_parser.cpp:147)
==7690== by 0x4050CD: PGMParser::get_pgm() (pgm_parser.cpp:94)
==7690== by 0x404D67: PGMParser::PGMParser(std::string const&) (pgm_parser.cpp:25)
==7690== by 0x404212: main (main.cpp:52)
==7690==
==7690== 12 bytes in 1 blocks are still reachable in loss record 5 of 11
==7690== at 0x4C298A0: operator new[](unsigned long) (vg_replace_malloc.c:389)
==7690== by 0x404A15: Matrix<Pixel>::Matrix(Matrix<Pixel> const&) (matrix.hpp:59)
==7690== by 0x404579: PGMImage::PGMImage(PGMImage const&) (pgm_image.cpp:31)
==7690== by 0x4024DD: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:57)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== 16 bytes in 1 blocks are still reachable in loss record 6 of 11
==7690== at 0x4C29180: operator new(unsigned long) (vg_replace_malloc.c:324)
==7690== by 0x40445E: PGMImage::PGMImage(unsigned int, unsigned int) (pgm_image.cpp:14)
==7690== by 0x405475: PGMParser::set_pgm_dimensions(std::vector<int, std::allocator<int> >) (pgm_parser.cpp:147)
==7690== by 0x4050CD: PGMParser::get_pgm() (pgm_parser.cpp:94)
==7690== by 0x404D67: PGMParser::PGMParser(std::string const&) (pgm_parser.cpp:25)
==7690== by 0x404212: main (main.cpp:52)
==7690==
==7690== 16 bytes in 1 blocks are still reachable in loss record 7 of 11
==7690== at 0x4C29180: operator new(unsigned long) (vg_replace_malloc.c:324)
==7690== by 0x40248A: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:49)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== 16 bytes in 1 blocks are still reachable in loss record 8 of 11
==7690== at 0x4C298A0: operator new[](unsigned long) (vg_replace_malloc.c:389)
==7690== by 0x403740: Matrix<Complex>::Matrix(unsigned int, unsigned int) (matrix.hpp:46)
==7690== by 0x4024A5: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:49)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== 16 bytes in 1 blocks are still reachable in loss record 9 of 11
==7690== at 0x4C29180: operator new(unsigned long) (vg_replace_malloc.c:324)
==7690== by 0x404564: PGMImage::PGMImage(PGMImage const&) (pgm_image.cpp:31)
==7690== by 0x4024DD: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:57)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== 24 bytes in 1 blocks are still reachable in loss record 10 of 11
==7690== at 0x4C29180: operator new(unsigned long) (vg_replace_malloc.c:324)
==7690== by 0x405464: PGMParser::set_pgm_dimensions(std::vector<int, std::allocator<int> >) (pgm_parser.cpp:147)
==7690== by 0x4050CD: PGMParser::get_pgm() (pgm_parser.cpp:94)
==7690== by 0x404D67: PGMParser::PGMParser(std::string const&) (pgm_parser.cpp:25)
==7690== by 0x404212: main (main.cpp:52)
==7690==
==7690== 24 bytes in 1 blocks are still reachable in loss record 11 of 11
==7690== at 0x4C29180: operator new(unsigned long) (vg_replace_malloc.c:324)
==7690== by 0x4024CB: PGMTransformation::PGMTransformation(PGMImage const&, std::string const&) (PGMTransformation.cpp:57)
==7690== by 0x404240: main (main.cpp:55)
==7690==
==7690== LEAK SUMMARY:
==7690== definitely lost: 0 bytes in 0 blocks
==7690== indirectly lost: 0 bytes in 0 blocks
==7690== possibly lost: 0 bytes in 0 blocks
==7690== still reachable: 160 bytes in 11 blocks
==7690== suppressed: 0 bytes in 0 blocks
==7690==
==7690== For counts of detected and suppressed errors, rerun with: -v
==7690== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我认为代码部分崩溃的矩阵模板如下:
template<typename T>
class Matrix
{
private:
T** matrix_;
unsigned int rows_;
unsigned int cols_;
public:
Matrix();
Matrix(unsigned int, unsigned int);
Matrix(Matrix const &);
~Matrix();
Matrix const &operator=(Matrix const &);
//more methods...
};
template<typename T>
Matrix<T>::Matrix()
: matrix_(0), rows_(0), cols_(0) {}
template<typename T>
Matrix<T>::Matrix(unsigned int rows, unsigned int cols)
{
matrix_ = new T*[rows];
for(unsigned int i=0; i < rows; i++)
matrix_[i] = new T[cols];
rows_ = rows;
cols_ = cols;
}
template<typename T>
Matrix<T>::Matrix(Matrix<T> const & m_orig)
{
rows_ = m_orig.rows_;
cols_ = m_orig.cols_;
matrix_ = new T*[rows_];
for(unsigned int i=0; i < rows_; i++)
{
matrix_[i] = new T[cols_];
for(unsigned int j=0; j < cols_; j++)
matrix_[i][j]=m_orig.matrix_[i][j];
}
}
template<typename T>
Matrix<T>::~Matrix()
{
for(unsigned int i=0; i < rows_; i++)
delete matrix_[i];
delete []matrix_;
rows_ = 0;
cols_ = 0;
}
template<typename T>
Matrix<T> const & Matrix<T>::operator=(Matrix const & m_orig)
{
if(this != &m_orig)
{
for(unsigned int k=0; k < rows_; k++)
delete matrix_[k];
delete matrix_;
rows_ = m_orig.rows_;
cols_ = m_orig.cols_;
matrix_ = new T*[rows_];
for(unsigned int i=0; i < rows_; i++)
{
matrix_[i] = new T[cols_];
for(unsigned int j=0; j < cols_; j++)
matrix_[i][j]=m_orig.matrix_[i][j];
}
}
return *this;
}
还有其他类可能会失败,但valgrind几乎会跟踪每个到矩阵容器的泄漏。 非常感谢您的帮助!
答案 0 :(得分:4)
你应该遵循相同的&#34;模式&#34;使用delete
进行取消分配与使用new
的分配进行1>,
for(unsigned int i=0; i < rows_; i++)
delete [] matrix_[i];
// ~~ notice []
delete []matrix_;
答案 1 :(得分:3)
您的赋值运算符不是异常安全的,并且无法使用正确版本的delete
:它使用delete matrix_
而不是delete[] matrix_
释放内存。鉴于目前的实施情况,您最好 更好地替换此版本:
template <typename T>
Matrix<T> const& Matrix<T>::operator= (Matrix<T> orig) {
this->swap(orig);
return *this;
}
template <typename T>
void Matrix<T>::swap(Matrix<T>& other) {
using std::swap;
swap(this->matrix_, other.matrix_);
}
除了解决上面提到的内存问题之外,它还使得实现强大的异常安全。当然,这样做假定复制构造函数,析构函数和swap()
正确实现,因为它们被用来实现这个赋值运算符:
const&
来获取副本可以减少副本数量。)析构函数也不正确:它使用delete matrix_[k]
而不是delete[] matrix_[k]
。传统上,对象以相反的构造顺序被破坏,而您的代码以相反的顺序销毁对象。我建议使用std::vector<std::vector<T>>
来维护Matrix<T>
内的数据。