cpp - valgrind - 大小为8的读取无效

时间:2014-03-26 10:36:59

标签: c++ memory-leaks valgrind

我很难理解valgrind的错误。我有一个名为Matrix的模板类,它有一些重载的运算符等......来做一些数学运算。 Matrixes在名为ExtendedKalmanFilter的类中使用。

这是valgrind追踪:

==3352== Invalid read of size 8
==3352==    at 0x804CC8F: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:285)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352==  Address 0x6a8b3c0 is 0 bytes after a block of size 48 alloc'd
==3352==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3352==    by 0x804C986: BOViL::math::Matrix<double>::operator=(BOViL::math::Matrix<double> const&) (Matrix.h:224)
==3352==    by 0x8051C62: BOViL::algorithms::ExtendedKalmanFilter::setUpEKF(BOViL::math::Matrix<double>, BOViL::math::Matrix<double>, BOViL::math::Matrix<double>) (ExtendedKalmanFilter.cpp:23)
==3352==    by 0x804B74F: testSegmentation() (TestSegmentation.cpp:37)
==3352==    by 0x805266D: main (main.cpp:16)
==3352== 
==3352== Invalid write of size 8
==3352==    at 0x804CC12: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:283)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352==  Address 0x6a8d210 is 0 bytes after a block of size 48 alloc'd
==3352==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3352==    by 0x804CBD8: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:279)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352== 
==3352== Invalid read of size 8
==3352==    at 0x804CC55: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:285)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352==  Address 0x6a8d210 is 0 bytes after a block of size 48 alloc'd
==3352==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3352==    by 0x804CBD8: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:279)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352== 
==3352== Invalid write of size 8
==3352==    at 0x804CC95: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:285)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352==  Address 0x6a8d210 is 0 bytes after a block of size 48 alloc'd
==3352==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3352==    by 0x804CBD8: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:279)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352== 
--3352-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--3352-- si_code=1;  Faulting address: 0x6F666562;  sp: 0x6800fa88

valgrind: the 'impossible' happened:
   Killed by fatal signal
==3352==    at 0x380C0AD4: ??? (in /usr/lib/valgrind/memcheck-x86-linux)
==3352==    by 0x380C12C5: ??? (in /usr/lib/valgrind/memcheck-x86-linux)
==3352==    by 0x38040A63: ??? (in /usr/lib/valgrind/memcheck-x86-linux)
==3352==    by 0x38040B36: ??? (in /usr/lib/valgrind/memcheck-x86-linux)
==3352==    by 0x3803EA4B: ??? (in /usr/lib/valgrind/memcheck-x86-linux)
==3352==    by 0x74206572: ???

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable
==3352==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3352==    by 0x804BD52: BOViL::math::Matrix<double>::Matrix(double const*, int, int) (Matrix.h:118)
==3352==    by 0x804CCF3: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:290)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)

这里是代码片段:

- &GT;矩阵界面

    template <typename type_> 
    class Matrix{
    public:     // Main interface
        Matrix();       // Default constructor
        Matrix(int _cols, int _rows);       // Empty matrix constructor
        Matrix(const type_* _mat, int _rows, int _cols);    // Full-defined matrix constructor
        Matrix(const Matrix& _mat);     // Copy constructor
        Matrix(Matrix&& _mat);          // Move constructor c++11

        ~Matrix();      // De-constructor

        type_* getMatrixPtr() const;
        int getWidth() const;
        int getHeight() const;

        void showMatrix() const;

   public:  // Overloaded Operators
        std::string operator<<(const Matrix<type_>& _mat) const;        // Operator for cout 666 TODO:
        type_& operator[](int _index);
        Matrix operator=(const Matrix& _mat);               // Assignement operator
        Matrix operator+(const Matrix& _mat) const;     // Add operator
        Matrix operator-(const Matrix& _mat) const;     // Sub operator
        Matrix operator*(const Matrix& _mat) const;     // Mul operator
        Matrix operator*(const type_ _scalar) const;        // Scalar operator
        Matrix operator^(const double _exp) const;      // Pow operator     666 TODO:

    public: // Other operations 666 TODO: Change names
        Matrix operator&(const Matrix& _mat) const;     // Projection operator._mat is projected to this
        Matrix transpose();                             // Transpose operator
        type_ determinant();                            // Determinant operator

    public:     // Various algorithms
        double norm();
        bool decompositionLU(Matrix& _L, Matrix& _U);
        bool decompositionCholesky(Matrix& _L, Matrix& _Lt);
        bool decompositionLDL(Matrix& _L, Matrix& _D, Matrix& _Lt);
        bool decompositionQR_GR(Matrix& _Q, Matrix& _R);        // QR decomposition using Householder reflexions algorithm.

        Matrix inverse();       // Using QR algorithm


    private:    // Private interface
        int mCols, mRows;
        type_* mPtr;

    };

- &gt;这里是矩阵崩溃的地方:

void ExtendedKalmanFilter::forecastStep(const double _incT){
    updateJf(_incT);

    mXfk = mJf * mXak;  <<<----- HERE CRASH, inside operator*

    mP = mJf * mP * mJf.transpose() + mQ;
}

准确地说,它在构造函数矩阵内崩溃(type_ * ptr,int _cols,int _rows);初始化指针时

template<typename type_> 
Matrix<type_> Matrix<type_>::operator* (const Matrix<type_>& _mat) const{
    if(mCols !=_mat.mRows)
        assert(false);

    type_* ptr = new type_[mRows*_mat.mCols];

    for(int i = 0; i < mRows ; i ++ ){
        for(int j = 0 ; j < mCols ; j ++){
            ptr[_mat.mCols * i + j] = 0;
            for(int k = 0 ; k < _mat.mRows ; k ++){
                ptr[_mat.mCols * i + j] += mPtr[mCols * i + k] * _mat.mPtr[_mat.mCols * k + j];
            }
        }
    }

    Matrix<type_> mat(ptr, mRows, _mat.mCols); <<< ----- HERE
    delete[] ptr;

    return mat;
}


template<typename type_> 
Matrix<type_>::Matrix(const type_* _matPtr, int _rows, int _cols):  mPtr(new type_[_cols*_rows]),
                                                                        mCols(_cols),
                                                                        mRows(_rows)        
    { <<<---- CRASH before getting into (So I suppose that crash in the new type_[_cols*_rows]
        for(int i = 0; i < _cols*_rows ; i ++){
            mPtr[i] = _matPtr[i];
        }
    }

最后,该类的析构函数是:

template<typename type_> 
Matrix<type_>::~Matrix(){
    if(mPtr)
        delete[] mPtr;
}

任何人都可以帮助我吗?我无法在Windows中尝试使用Visual Studio进行调试,并在linux中使用valgrind进行调试。

提前致谢

2 个答案:

答案 0 :(得分:15)

你的程序看起来很乱,内存也被破坏了。通过查看您的代码片段,这有点难以找到。

但是正如您在问题中提到的那样,您可以使用 Valgrind附加您的程序。所以您可能想要附加您的程序(a.out)。

  

$ valgrind --tool = memcheck --db-attach = yes ./a.out

这样,当您检测到第一个内存错误时,Valgrind会将您的程序附加到调试器中,以便您可以进行实时调试(GDB)。这应该是理解和解决问题的最佳方式。

一旦你能够弄清楚你的第一个错误,修复它并重新运行它,看看你得到的其他错误。这个步骤应该完成,直到Valgrind没有报告错误。

答案 1 :(得分:4)

你的第一个错误是:

==3352== Invalid read of size 8
==3352==    at 0x804CC8F: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:285)
==3352==    by 0x8051F91: BOViL::algorithms::ExtendedKalmanFilter::forecastStep(double) (ExtendedKalmanFilter.cpp:48)
==3352==    by 0x8051F25: BOViL::algorithms::ExtendedKalmanFilter::stepEKF(BOViL::math::Matrix<double> const&, double) (ExtendedKalmanFilter.cpp:39)
==3352==    by 0x804B98F: testSegmentation() (TestSegmentation.cpp:53)
==3352==    by 0x805266D: main (main.cpp:16)
==3352==  Address 0x6a8b3c0 is 0 bytes after a block of size 48 alloc'd
==3352==    at 0x402B454: operator new[](unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3352==    by 0x804C986: BOViL::math::Matrix<double>::operator=(BOViL::math::Matrix<double> const&) (Matrix.h:224)
==3352==    by 0x8051C62: BOViL::algorithms::ExtendedKalmanFilter::setUpEKF(BOViL::math::Matrix<double>, BOViL::math::Matrix<double>, BOViL::math::Matrix<double>) (ExtendedKalmanFilter.cpp:23)
==3352==    by 0x804B74F: testSegmentation() (TestSegmentation.cpp:37)
==3352==    by 0x805266D: main (main.cpp:16)

简称:

==3352== Invalid read of size 8
==3352==    at 0x804CC8F: BOViL::math::Matrix<double>::operator*(BOViL::math::Matrix<double> const&) const (Matrix.h:285)
==3352==  Address 0x6a8b3c0 is 0 bytes after a block of size 48 alloc'd

知道矩阵是double,这意味着矩阵内的数组被分配为包含6个元素(48/sizeof double)。但是,您在块之后访问0个字节,这意味着您正在访问元素索引6。

因此,您需要验证两件事:

  1. 6是正确的吗?该数组是否应包含6个元素?
  2. Matrix.h的第285行(可能在for圈内,

    Matrix<type_> mat(ptr, mRows, _mat.mCols); <<< ----- HERE
    

    您需要检查您为数组提供的索引。可能,你会发现数组被索引为6,你应该找出为什么