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:
- Is 6 correct? Should the array contain 6 elements?
-
At line 285 of
Matrix.h
, which is likely inside thefor
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.