cpp - valgrind - Invalid read of size 8

I'm getting mad understanding that valgrind error. I've got a template class called Matrix that has some overloaded operators etc... to do some mathematical operations. Matrixes are used inside a class called ExtendedKalmanFilter.

Here is the valgrind trace:

==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)

And here fragments of the code:

--> Matrix interface

    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;

    };

-->And here is where matrix crash:

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

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

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

To be precise, it crash inside the constructor matrix(type_* ptr, int _cols, int _rows); while initializing the pointer

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];
        }
    }

Finally, the destructor of the class is:

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

Can anyone help me? I cant find the trouble I tryed debugging with Visual Studio in windows and with valgrind in linux.

Thanks in advance


Solution 1:

Your program seems to have big mess and memory is getting corrupted. This is is bit difficult to find by looking out your code snippet.

However as you have mentioned in your question that you are able to attach your program using Valgrind. So you may want to attach your program(a.out).

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

This way Valgrind would attach your program in the debugger when your first memory error is detected so that you can do live debugging(GDB). This should be the best possible way to understand and resolve your problem.

Once you are able to figure it out your first error, fix it and rerun it and see what are other errors you are getting.This steps should be done till no error is getting reported by Valgrind.

Solution 2:

Your first error says:

==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)

which in short means:

==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

Knowing that your matrix is of double, that means the array inside the matrix is allocated to contain 6 elements (48/sizeof double). However, you are accessing 0 bytes after the block, which means you are accessing exactly element index 6.

So there are two things that you need to verify:

  1. Is 6 correct? Should the array contain 6 elements?
  2. At line 285 of Matrix.h, which is likely inside the for loops, not here:

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

    you need to examine what indices you are giving to the array. Likely, you will find the array being indexed at 6 and that's where you should figure out why.