cpp - valgrind - Invalid read of size 8

17,547

Solution 1

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.

Solution 2

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.

Share:
17,547
Bardo91
Author by

Bardo91

A motivated student of Engineering of the University at Seville. The Goal of my life is create a completely functional orthopaedic for replacing a human part of the body like a "Robotic Arm" or who knows... maybe the Ironman suit!

Updated on June 17, 2022

Comments

  • Bardo91
    Bardo91 almost 2 years

    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

  • Shahbaz
    Shahbaz about 10 years
    I didn't know about --db-attach, that will certainly come in handy!
  • Mantosh Kumar
    Mantosh Kumar about 10 years
    @VisaisRacism: yes it is really wonderful feature provided by Valgrind as process would break and attached in GDB or any other debugger when error is detected otherwise it would silently continue to monitor our process. I have found it really useful in the past as it provides the way to do live debugging at the point of error.
  • Bardo91
    Bardo91 about 10 years
    Oh! the size of the matrix was right, but as you said, I was accessing over the size of the array inside de loops... I feel so fool hahah. Thanks thanks and thanks.
  • Diego Medaglia
    Diego Medaglia about 9 years
    This helped me spot the cause of an error that was happening in a seemingly unrelated location. Thanks!
  • Lack
    Lack almost 7 years
    For posterity, --db-attach was removed in valgrind 3.11. The new instructions to use gdb are here: valgrind.org/docs/manual/…