why does valgrind detect uninitialised values only so late - c++

I want to understand the valgrind log messages and use the following code
#include <iostream>
int main()
{
int numbers[] = {1,2,3,4,5,6,7,8,9,10};
int length = sizeof(numbers) / sizeof(numbers[0]);
std::cout << "length: " << length << std::endl;
for (int i = 0; i < length + 10; ++i)
{
int number = numbers[i];
if (number > 5)
{
std::cout << number << " is greater than 5" << std::endl;
} else {
std::cout << number << " is less or equal 5" << std::endl;
}
}
}
to produce uninitialised values. If I run the program in valgrind I don't receive a corresponding message. If I run the for-loop to length + 10 valgrind detects uninitialised values.
Why does valgrind detect the unitialised values only so late?
==2484== Conditional jump or move depends on uninitialised value(s)
==2484== at 0x108A3C: main (arrays.cpp:11)
==2484== Uninitialised value was created by a stack allocation
==2484== at 0x51E6ABB: (below main) (libc-start.c:137)
==2484==
==2484== Conditional jump or move depends on uninitialised value(s)
==2484== at 0x4F43C0A: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x108A85: main (arrays.cpp:15)
==2484== Uninitialised value was created by a stack allocation
==2484== at 0x51E6ABB: (below main) (libc-start.c:137)
==2484==
==2484== Use of uninitialised value of size 8
==2484== at 0x4F4370E: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x4F43C33: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x108A85: main (arrays.cpp:15)
==2484== Uninitialised value was created by a stack allocation
==2484== at 0x51E6ABB: (below main) (libc-start.c:137)
==2484==
==2484== Conditional jump or move depends on uninitialised value(s)
==2484== at 0x4F4371B: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x4F43C33: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x108A85: main (arrays.cpp:15)
==2484== Uninitialised value was created by a stack allocation
==2484== at 0x51E6ABB: (below main) (libc-start.c:137)
==2484==
==2484== Conditional jump or move depends on uninitialised value(s)
==2484== at 0x4F43C66: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484== by 0x108A85: main (arrays.cpp:15)
==2484== Uninitialised value was created by a stack allocation
==2484== at 0x51E6ABB: (below main) (libc-start.c:137)
EDIT: I changed the code. THis is the whole code i used.
compile: g++ -c -g3 arrays.cpp arrays.cpp
valgrind: valgrind --tool=memcheck --track-origins=yes --num-callers=100 --log-file=uv_log.txt ./arrays
EDIT 2:
length: 10
1 is less or equal 5
2 is less or equal 5
3 is less or equal 5
4 is less or equal 5
5 is less or equal 5
6 is greater than 5
7 is greater than 5
8 is greater than 5
9 is greater than 5
10 is greater than 5
-882498304 is less or equal 5
-188984184 is less or equal 5
1084208 is greater than 5
0 is less or equal 5
85879703 is greater than 5
0 is less or equal 5
0 is less or equal 5

You don't actually check for uninitialized access. You check for index out of bounds access. In your case, the out of bounds access is on the stack, so you access some memory, which is on the stack. And you're lucky, because the whole accessed area is on the stack, so you don't get an invalid read. Your program reads some data of the stack, which happens to be initialized for the length+1 case (because there is some other thing written to it, for example, it can be function parameter, other local variable or the function's return address), so valgrind is not able to report any error.
But for the length+10 case, it is large enough to actually read from some uninitialized memory. And I bet, if you increase 10 to a much larger number, you'll get invalid read (which causes segmentation fault).

Related

C++ Valgrind: Conditional jump or move depends on uninitialised value(s)

So I'm implementing a weighted digraph with templates using a dynamic matrix (which I also implemented).
The thing is, when I use my Matrix class on its own it works fine, but inside the Graph class it just doesn't and I don't understand why. I was hoping someone could help me out.
Here is the Matrix class. I tested it directly on main.cpp with Valgrind and it didn't show anything.
template <typename Type>
class Matrix {
private:
Type** matrix;
unsigned size;
Type null;
public:
Matrix();
Matrix(unsigned size, Type null);
Matrix(const Matrix& matrix);
~Matrix();
Type getData(unsigned row, unsigned col);
void insert(Type data, unsigned row, unsigned col);
void freeMatrixResources(Type** matrix);
void resize(unsigned size);
void assignNull(unsigned int beginRow, unsigned int endRow, unsigned int beginCol, unsigned int endCol);
void copyData(Type** matrix, unsigned begin, unsigned end);
void printMatrix();
Type operator()(unsigned int row, unsigned int col);
friend ostream& operator << (ostream& o, const Matrix<Type> &m);
};
template <typename Type>
ostream& operator << (ostream& out, const Matrix<Type> &m) {
for (int i = 0; i < m.size; ++i) {
out << "\t\t";
for (int j = 0; j < m.size; ++j) {
out << m.getData(i, j) << "\t";
}
out << "\n";
}
out << "\n";
return out;
}
template <typename Type>
Type Matrix<Type>:: operator()(unsigned int row, unsigned int col) {
return matrix[row][col];
}
template <typename Type>
Matrix<Type>:: Matrix() {
matrix = 0;
size = 0;
null = 0;
}
template <typename Type>
Matrix<Type>:: Matrix(unsigned size, Type null) {
matrix = new Type*[size];
for (int i = 0; i < size; ++i)
matrix[i] = new Type[size];
this->size = size;
this->null = null;
assignNull(0, size, 0, size);
}
template <typename Type>
Matrix<Type>:: Matrix(const Matrix<Type> &matrix) {
this->matrix = new Type*[matrix.size];
for (int i = 0; i < matrix.size; ++i)
matrix[i] = new Type[matrix.size];
copyData(matrix,0,0);
}
template <typename Type>
Matrix<Type>:: ~Matrix() {
freeMatrixResources(matrix);
}
template <typename Type>
Type Matrix<Type>:: getData(unsigned row, unsigned col) {
return matrix[row][col];
}
template <typename Type>
void Matrix<Type>:: insert(Type data, unsigned int row, unsigned int col) {
matrix[row][col] = data;
}
template <typename Type>
void Matrix<Type>:: freeMatrixResources(Type** matrix) {
for (int i = 0; i < size; ++i) {
delete [] matrix[i];
}
delete [] matrix;
}
template <typename Type>
void Matrix<Type>:: resize(unsigned int newSize) {
if (this->size != newSize) {
Type** aux = matrix;
matrix = new Type*[newSize];
for (int i = 0; i < newSize; ++i)
matrix[i] = new Type[newSize];
if (this->size < newSize) {
copyData(aux, 0, this->size);
assignNull(this->size, newSize, 0, newSize);
assignNull(0, newSize, this->size, newSize);
}
else
copyData(aux, 0, newSize);
freeMatrixResources(aux);
this->size = newSize;
}
}
template <typename Type>
void Matrix<Type>:: assignNull(unsigned int beginRow, unsigned int endRow, unsigned int beginCol, unsigned int endCol) {
for (int i = beginRow; i < endRow; ++i) {
for (int j = beginCol; j < endCol; ++j) {
matrix[i][j] = null;
}
}
}
template <typename Type>
void Matrix<Type>:: copyData(Type** matrix, unsigned int begin, unsigned int end) {
for (int i = begin; i < end; ++i) {
for (int j = begin; j < end; ++j) {
this->matrix[i][j] = matrix[i][j];
}
}
}
template <typename Type>
void Matrix<Type>:: printMatrix() {
for (int i = 0; i < size; ++i) {
cout << "\t\t";
for (int j = 0; j < size; ++j) {
cout << matrix[i][j] << "\t";
}
cout << "\n";
}
cout << "\n";
}
But then, when I run the Graph program with valgrind --tool=memcheck --leak-check=full "./cmake-build-debug/graphTemplates" the output says Uninitialised value was created by a stack allocation, Conditional jump or move depends on uninitialised value(s)
==155342== Memcheck, a memory error detector
==155342== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==155342== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==155342== Command: ./cmake-build-debug/graphTemplates
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109BEC: Matrix<int>::resize(unsigned int) (Matrix.h:100)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109C0D: Matrix<int>::resize(unsigned int) (Matrix.h:103)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x483C530: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==155342== by 0x109C1A: Matrix<int>::resize(unsigned int) (Matrix.h:103)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109C39: Matrix<int>::resize(unsigned int) (Matrix.h:104)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109C4B: Matrix<int>::resize(unsigned int) (Matrix.h:105)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x483C530: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==155342== by 0x109C74: Matrix<int>::resize(unsigned int) (Matrix.h:105)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109C88: Matrix<int>::resize(unsigned int) (Matrix.h:107)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109D51: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:122)
==155342== by 0x109CC8: Matrix<int>::resize(unsigned int) (Matrix.h:109)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109D5F: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:123)
==155342== by 0x109CC8: Matrix<int>::resize(unsigned int) (Matrix.h:109)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109D51: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:122)
==155342== by 0x109CE9: Matrix<int>::resize(unsigned int) (Matrix.h:110)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109D5F: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:123)
==155342== by 0x109CE9: Matrix<int>::resize(unsigned int) (Matrix.h:110)
==155342== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155342== by 0x109327: main (main.cpp:36)
==155342==
==155342== Use of uninitialised value of size 8
==155342== at 0x109A5E: Matrix<int>::insert(int, unsigned int, unsigned int) (Matrix.h:87)
==155342== by 0x109794: Graph<int, int>::addEdge(int, int, int) (Graph.h:121)
==155342== by 0x109327: main (main.cpp:36)
==155342==
Edge connecting 3 and 1 with cost 7 added successfully!
==155342== Conditional jump or move depends on uninitialised value(s)
==155342== at 0x109EB3: Matrix<int>::freeMatrixResources(int**) (Matrix.h:92)
==155342== by 0x109A99: Matrix<int>::~Matrix() (Matrix.h:77)
==155342== by 0x10958E: Graph<int, int>::~Graph() (Graph.h:84)
==155342== by 0x10934B: main (main.cpp:30)
==155342==
==155342==
==155342== HEAP SUMMARY:
==155342== in use at exit: 0 bytes in 0 blocks
==155342== total heap usage: 14 allocs, 14 frees, 73,900 bytes allocated
==155342==
==155342== All heap blocks were freed -- no leaks are possible
==155342==
==155342== Use --track-origins=yes to see where uninitialised values come from
==155342== For lists of detected and suppressed errors, rerun with: -s
==155342== ERROR SUMMARY: 35 errors from 13 contexts (suppressed: 0 from 0)
valentina#valentina-Lenovo-Yoga-C740-14IML:~/Documentos/Algo II/Plantillvalentina#valentina-Lenovo-Yoga-C740-14IML:~/Documentos/Algo II/Plantillvalentina#valentina-Lenovo-Yoga-C740-14IML:~/Documentos/Algo II/Plantillvalentina#valentina-Lenovo-Yoga-C740-14IML:~/Documentos/Algo II/Plantillas de estructuras/graphTemplates$ v
algrind --tool=memcheck --xml=yes --xml-file=/tmp/valgrind --leak-check=full "./cmake-build-debug/graphTemplates"
========================= GRAPH ================================
Edge connecting 1 and 2 with cost 5 added successfully!
9999999 5
9999999 9999999
Edge connecting 1 and 2 with cost 4 added successfully!
Edge connecting 3 and 1 with cost 7 added successfully!
================================================================
valentina#valentina-Lenovo-Yoga-C740-14IML:~/Documentos/Algo II/Plantillas de estructuras/graphTemplates$ valgrind --tool=memcheck --track-origins=yes --leak-check=full "./cmake-build-debug/graphTemplates"==155816== Memcheck, a memory error detector
==155816== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==155816== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==155816== Command: ./cmake-build-debug/graphTemplates
==155816==
========================= GRAPH ================================
Edge connecting 1 and 2 with cost 5 added successfully!
9999999 5
9999999 9999999
Edge connecting 1 and 2 with cost 4 added successfully!
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109BEC: Matrix<int>::resize(unsigned int) (Matrix.h:100)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109C0D: Matrix<int>::resize(unsigned int) (Matrix.h:103)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x483C530: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==155816== by 0x109C1A: Matrix<int>::resize(unsigned int) (Matrix.h:103)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109C39: Matrix<int>::resize(unsigned int) (Matrix.h:104)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109C4B: Matrix<int>::resize(unsigned int) (Matrix.h:105)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x483C530: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==155816== by 0x109C74: Matrix<int>::resize(unsigned int) (Matrix.h:105)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109C88: Matrix<int>::resize(unsigned int) (Matrix.h:107)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109D51: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:122)
==155816== by 0x109CC8: Matrix<int>::resize(unsigned int) (Matrix.h:109)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109D5F: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:123)
==155816== by 0x109CC8: Matrix<int>::resize(unsigned int) (Matrix.h:109)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109D51: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:122)
==155816== by 0x109CE9: Matrix<int>::resize(unsigned int) (Matrix.h:110)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109D5F: Matrix<int>::assignNull(unsigned int, unsigned int, unsigned int, unsigned int) (Matrix.h:123)
==155816== by 0x109CE9: Matrix<int>::resize(unsigned int) (Matrix.h:110)
==155816== by 0x10974B: Graph<int, int>::addEdge(int, int, int) (Graph.h:119)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Use of uninitialised value of size 8
==155816== at 0x109A5E: Matrix<int>::insert(int, unsigned int, unsigned int) (Matrix.h:87)
==155816== by 0x109794: Graph<int, int>::addEdge(int, int, int) (Graph.h:121)
==155816== by 0x109327: main (main.cpp:36)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816== Conditional jump or move depends on uninitialised value(s)
==155816== at 0x109EB3: Matrix<int>::freeMatrixResources(int**) (Matrix.h:92)
==155816== by 0x109A99: Matrix<int>::~Matrix() (Matrix.h:77)
==155816== by 0x10958E: Graph<int, int>::~Graph() (Graph.h:84)
==155816== by 0x10934B: main (main.cpp:30)
==155816== Uninitialised value was created by a stack allocation
==155816== at 0x109289: main (main.cpp:7)
==155816==
==155816==
==155816== HEAP SUMMARY:
==155816== in use at exit: 0 bytes in 0 blocks
==155816== total heap usage: 14 allocs, 14 frees, 73,900 bytes allocated
==155816==
==155816== All heap blocks were freed -- no leaks are possible
==155816==
==155816== For lists of detected and suppressed errors, rerun with: -s
==155816== ERROR SUMMARY: 35 errors from 13 contexts (suppressed: 0 from 0)
Here are the methods in the Graph class which Valgrind complains
template<typename Type, typename Cost>
Graph<Type, Cost>:: ~Graph() {
delete costsMatrix;
delete vertices;
}
template<typename Type, typename Cost>
void Graph<Type, Cost>:: addEdge(Type begin, Type end, Cost cost) {
if (existsVertex(begin) && existsVertex(end)) {
costsMatrix->insert(cost, vertices->getPosition(begin), vertices->getPosition(end));
}
else if (existsVertex(begin)) {
costsMatrix->resize(elements + 1);
vertices->insertAtEnd(end);
costsMatrix->insert(cost, vertices->getPosition(begin), elements);
elements += 1;
}
else if(existsVertex(end)) {
costsMatrix->resize(elements + 1);
vertices->insertAtEnd(begin);
costsMatrix->insert(cost, elements, vertices->getPosition(end));
elements += 1;
}
else {
costsMatrix->resize(elements + 2);
vertices->insertAtEnd(begin);
vertices->insertAtEnd(end);
elements += 2;
costsMatrix->insert(cost, vertices->getPosition(begin), vertices->getPosition(end));
}
cout << "\t\tEdge connecting " << begin << " and " << end << " with cost " << cost << " added successfully!\n";
}
I know I could use std library for the matrix, but I was asked not to
Update: The problem was that in one of the paths I had, I was not initializing the attribute elements correctly. Thanks all for the help
The error says that there's an uninitialized value being used in a "conditional jump or move", which basically means a conditional statement such as if. It says that the error is happening the Matrix<int>::resize(unsigned int) method. So it must be referring to
if (this->size != newSize)
which means that either this->size or newSize is uninitialized.
Another valgrind error says that an uninitialized value is being used in operator new[](unsigned long) being called from the resize method. So that must be referring to
matrix = new Type*[newSize];
So this has narrowed down the problem to the newSize variable. This is a function parameter, so we have to step back to where the function is called. The stack trace says it was called from Graph<int, int>::addEdge(int, int, int). All the calls are similar to:
costsMatrix->resize(elements + 1);
so the problem must be that the elements variable is not initialized.

malloc() memory corruption by writing an int array only for a specific amount

I have a memory corruption in my code given as
*** Error in `./match': malloc(): memory corruption: 0x0000000001036470 ***
Aborted (core dumped)
Strangely this happens not before having an input of about 30-40 elements.
Since I couldn't figure out what's going on I did some research and read that valgrind is a good choice. I'm very new into this so I ran valgrind via two options (not sure the one makes sense) which points at subsequent code lines:
void match(vector<APD> apdvec_database, const char* OUTPUTFILE, bool EXTRACT_APD_VALUE)
{
(...)
const int N = apdvec_database.size();
vector<vector<double> > cost (N, vector<double>(N,0));
(...)
// Calculate amount of edges
double number=0;
double n=N;
double k=2;
number=binom(n, k);
// convert edges
int node_num;
long int edge_num;
int* edges;
double* weights;
node_num=N;
edge_num=(int)number;
[line 561:] edges = new int[2*edge_num];
weights = new double[edge_num];
cout << "\t\t " << node_num << " APDs and " << edge_num << " edges calculated" << endl;
int e=0;
for(size_t i = 0; i<apdvec_database.size(); i++)
{
for(size_t j = 0; j<apdvec_database.size(); j++)
{
if(i!=j)
{
// Assign edges among themselves
[line 575:] edges[2*e] = (int)i;
edges[2*e+1] = (int)j;
// Use only triangular matrix with diagonals
if(j>i){ weights[e] = (double)cost[i][j];}
else{ if((int)+(int)j<node_num) weights[e] = (double)cost[i][j]; }
e++;
}
}
}
Due to the output I marked two specific lines via [line] at the beginning: The output is:
valgrind options: --tool=memcheck --leak-check=yes
==24195== at 0x40D5CE: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:575)
==24195== by 0x410866: main (match.cpp:680)
==24195== Address 0x8be5a38 is 0 bytes after a block of size 11,448 alloc'd
==24195== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195== by 0x40D4A6: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:561)
==24195== by 0x410866: main (match.cpp:680)
==24195==
==24195== Invalid write of size 4
==24195== at 0x40D5D2: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:576)
==24195== by 0x410866: main (match.cpp:680)
==24195== Address 0x8be5a3c is 4 bytes after a block of size 11,448 alloc'd
==24195== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195== by 0x40D4A6: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:561)
==24195== by 0x410866: main (match.cpp:680)
==24195==
==24195== Invalid write of size 8
==24195== at 0x40D607: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:580)
==24195== by 0x410866: main (match.cpp:680)
==24195== Address 0x158e86c8 is 0 bytes after a block of size 11,448 alloc'd
==24195== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195== by 0x40D4D3: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:562)
==24195== by 0x410866: main (match.cpp:680)
==24195==
==24195== Invalid write of size 8
==24195== at 0x40D5EA: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:579)
==24195== by 0x410866: main (match.cpp:680)
==24195== Address 0x158e87a0 is 128 bytes inside a block of size 184 free'd
==24195== at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195== by 0x508A5B8: THashList::Delete(char const*) (THashList.cxx:199)
==24195== by 0x5515ACF: TDirectoryFile::Close(char const*) (TDirectoryFile.cxx:562)
==24195== by 0x550A549: TFile::Close(char const*) (TFile.cxx:935)
==24195== by 0x410623: database_irradiated(char const*, bool, std::vector<APD, std::allocator<APD> >&, double&) (match.cpp:317)
==24195== by 0x410820: main (match.cpp:655)
==24195==
valgrind options: -fno-inline
==23041== Invalid write of size 4
==23041== at 0x416D17: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== Address 0x8be5a38 is 0 bytes after a block of size 11,448 alloc'd
==23041== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041== by 0x416C6E: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==
==23041== Invalid write of size 4
==23041== at 0x416D1B: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== Address 0x8be5a3c is 4 bytes after a block of size 11,448 alloc'd
==23041== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041== by 0x416C6E: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==
==23041== Invalid write of size 8
==23041== at 0x416D72: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== Address 0x158e86c8 is 0 bytes after a block of size 11,448 alloc'd
==23041== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041== by 0x416C9B: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==
==23041== Invalid write of size 8
==23041== at 0x416D45: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== Address 0x158e87a0 is 128 bytes inside a block of size 184 free'd
==23041== at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041== by 0x508A5B8: THashList::Delete(char const*) (THashList.cxx:199)
==23041== by 0x5515ACF: TDirectoryFile::Close(char const*) (TDirectoryFile.cxx:562)
==23041== by 0x550A549: TFile::Close(char const*) (TFile.cxx:935)
==23041== by 0x417901: database_irradiated(char const*, bool, std::vector<APD, std::allocator<APD> >&, double&) (in /home/ben/analysis/APDs/match/Combine/match)
==23041== by 0x417A6D: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==
Interestingly via valgrind the program does not get stuck resp. does not throw a malloc() and instead it even ends successfully with reasonable output.
I obviously forget to comment further here: Nevertheless, I had to declare each variable clearly. Probably there was a conflict because I included Cern ROOT framework. But this was then solved anyhow by declaring each variable with care.

Can valgrind report a memory address of a lost block (for debugging recursive function calls)?

This question is the most similar to mine, but it's rather old, so I wonder if anything has changed since then.
The valgrind output for me is:
==29443== 109 (16 direct, 93 indirect) bytes in 2 blocks are definitely lost in loss record 270 of 309
==29443== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29443== by 0x4F4E8DB: grl::Configuration::Configuration(grl::Configuration const&) (configuration.h:192)
==29443== by 0x4F49973: grl::YAMLConfigurator::load(YAML::Node const&, grl::Configuration*, std::string const&) (configurable.cpp:74)
==29443== by 0x4F499FC: grl::YAMLConfigurator::load(YAML::Node const&, grl::Configuration*, std::string const&) (configurable.cpp:75)
==29443== by 0x4F499FC: grl::YAMLConfigurator::load(YAML::Node const&, grl::Configuration*, std::string const&) (configurable.cpp:75)
==29443== by 0x4F499FC: grl::YAMLConfigurator::load(YAML::Node const&, grl::Configuration*, std::string const&) (configurable.cpp:75)
==29443== by 0x40C78E: grl::YAMLConfigurator::load(std::string, grl::Configuration*, std::string const&) (configurable.h:321)
==29443== by 0x40B897: main (deployer.cpp:180)
Program is configured at the start with recursive calls of reading from yaml file and storing all required parameters in a map as a pair (name, allocated address). I can print these pairs. Therefore, if valgrind could tell me an address of lost values then I could get a name of a parameter and check why it is not freed.
If the functionality is not possible, what else can I use?
You can run your program under valgrind+gdb, using vgdb.
See http://www.valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver
Then you can use various valgrind memcheck monitor commands to do
leak search and have the addresses/sizes of leaked blocks.
See http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.monitor-commands

Level 3 complex BLAS functions throwing out illegal value error

I am writing a function which calls Fortran functions for complex matrix matrix multiplication. I am calling the CGEMM_ and ZGEMM_ functions for complex multiplication. Since all xGEMM_ functions are essentially the same I copied the code from SGEMM_ to CGEMM__ and ZGEMM_. The only change made were the respective data types. The SGEMM_ and DGEMM_ functions are working fine but CGEMM_ throws the error. All inputs are the same as well.
** On entry to CGEMM parameter number 13 had an illegal value
and zgemm_ throws
** On entry to ZGEMM parameter number 1 had an illegal value
I really have no idea what's going on. Is this some kind of bug in the liblapack package? I am using liblapack-dev package. I made a smaller version of my big code and i am still getting the same error with CGEMM_.
I am running a 32-bit system and was wondering if that was the problem.
Code:
#include<iostream>
using namespace std;
#include<stdlib.h>
#include<string.h>
#include<complex>
typedef complex<float> c_float;
extern "C"
{c_float cgemm_(char*,char*,int*,int*,int*,c_float*, c_float[0],int*,c_float[0],int*,c_float*,c_float[0],int*);//Single Complex Matrix Multiplication
}
c_float** allocate(int rows, int columns)
{
c_float** data;
// Allocate Space
data = new c_float*[columns]; //Allocate memory for using multidimensional arrays in column major format.
data[0] = new c_float[rows*columns];
for (int i=0; i<columns; i++)
{
data[i] = data[0] + i*rows;
}
// Randomize input
for (int i=0; i<columns; i++)
{for (int j=0; j<rows; j++)
{
data[j][i] =complex<double>(drand48()*10 +1,drand48()*10 +1); //Randomly generated matrix with values in the range [1 11)
}
}
return(data);
}
// Destructor
void dest(c_float** data)
{
delete [] data[0];
delete [] data;
}
// Multiplication
void mult(int rowsA,int columnsA, int rowsB,int columnsB)
{
c_float **matA,**matB,**matC;
char transA, transB;
int m,n,k,LDA,LDB,LDC;
c_float *A,*B,*C;
c_float alpha(1.0,0.0);
c_float beta(0.0,0.0);
matA = allocate(rowsA,columnsA);
matB = allocate(rowsB,columnsB);
matC = allocate(rowsA,columnsB);
transA = 'N';
transB = 'N';
A = matA[0];
B = matB[0];
m = rowsA;
n = columnsB;
C = matC[0];
k = columnsA;
LDA = m;
LDB = k;
LDC = m;
cout<<"Matrix A"<<endl;
for (int i=0; i<rowsA; i++)
{for (int j=0; j<columnsA; j++)
{
cout<<matA[i][j];
cout<<" ";
}cout<<endl;
}
cout<<"Matrix B"<<endl;
for (int i=0; i<rowsB; i++)
{for (int j=0; j<columnsB; j++)
{
cout<<matB[i][j];
cout<<" ";
}cout<<endl;
}
cgemm_(&transA,&transB,&m,&n,&k,&alpha,A,&LDA,B,&LDB,&beta,C,&LDC);
cout<<"Matrix A*B"<<endl;
for (int i=0; i<rowsA; i++)
{for (int j=0; j<columnsB; j++)
{
cout<<matC[i][j];
cout<<"";
}
cout<<endl;
}
dest(matA);
dest(matB);
dest(matC);
}
main()
{
mult (2,2,2,2);
}
The output and valgrind report are as follows:
-----------------------------------------
Compilation using g++ -g -o matrix Matrix_multiplication.cpp -lblas -llapack -lgfortran
./matrix gives
Matrix A
(1.00985,1) (1.91331,4.64602)
(2.76643,1.41631) (5.87217,1.92298)
Matrix B
(5.54433,6.2675) (6.6806,10.3173)
(9.31292,3.33178) (1.50832,6.56094)
** On entry to CGEMM parameter number 1 had an illegal value
Valgrind output looks like
==4710== Memcheck, a memory error detector
==4710== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4710== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==4710== Command: ./o
==4710== Parent PID: 3337
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46E5096: lsame_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x46DD683: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46DD686: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46E5096: lsame_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x46DD7B1: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46DD7B4: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46E5096: lsame_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x46DD859: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46DD85C: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710==
==4710== HEAP SUMMARY:
==4710== in use at exit: 120 bytes in 6 blocks
==4710== total heap usage: 43 allocs, 37 frees, 13,897 bytes allocated
==4710==
==4710== LEAK SUMMARY:
==4710== definitely lost: 0 bytes in 0 blocks
==4710== indirectly lost: 0 bytes in 0 blocks
==4710== possibly lost: 0 bytes in 0 blocks
==4710== still reachable: 120 bytes in 6 blocks
==4710== suppressed: 0 bytes in 0 blocks
==4710== Rerun with --leak-check=full to see details of leaked memory
==4710==
==4710== For counts of detected and suppressed errors, rerun with: -v
==4710== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
EDIT: The question was modified with a code that can be run. The problem remains the same and the nature of the question has not changed.
The answer about the length of character variables in Fortran is essentially correct, but that is not your problem here. Fixed length character variables of functions inside the blas library will probably not read the length from a function argument. I checked this for a function and even at -O0 the length was a compile-time constant.
The cause of your particular problem is the definition c_float cgemm_(..., where you tell the compiler that cgemm_ returns a c_float. Normally, return values are put in a register, but when they are too large they can also go on the stack. In your case, on a 32bit system, this seems to be the case for the 8-byte c_float. Defining the function to be void cgemm_ (as it should be) or even int cgemm_ (which will use a register) solves the issue.
The take-home message is "don't do this", as this is a hackish way of calling and will cause headaches when dealing with different platforms/compilers. It is much better to use the cblas interface, or a C++ library for blas operations.
I don't see the lengths of the transA or transB strings being passed to the xgemm_ call.
Character dummies in Fortran are accompanied by a 'hidden' length argument. The convention used by GCC 4.9.0, for example, for this is described more here:
https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/Argument-passing-conventions.html.
The positioning of these hidden arguments in the argument list is platform dependent. On Linux they are placed after all the explicit arguments.
Consider s.f90
Subroutine s(c, r)
Character (*), Intent (In) :: c
Real, Intent (In) :: r
Print '(3A,I0,A)', 'c = "', c, '", (len(c)=', len(c), ')'
Print *, 'r = ', r
End Subroutine
and main.c
#include <string.h>
int main(void)
{
char c[1+1];
float r=4.2;
strcpy(c,"A");
s_(c,&r,1);
}
For running on Linux I am passing 1 as the (hidden in Fortran) third argument for s, representing the length of my string.
Compiling and running with gfortran gives me
> gfortran -g main.c s.f90 && ./a.out
c = "A", (len(c)=1)
r = 4.19999981
So probably your xgemm_ calls should be ...,&LDC,1,1);?

"points to uninitialised byte(s)" Valgrind errors

I've been using Valgrind to look for memory leaks in my code, and while no memory leaks are being found, some errors are reported all of them originating at a single function/class method:
==17043== ERROR SUMMARY: 10100 errors from 3 contexts (suppressed: 0 from 0)
==17043==
==17043== 100 errors in context 1 of 3:
==17043== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==17043== at 0x5441DA2: send (send.c:28)
==17043== by 0x404C2D: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== by 0x404F1C: unix_socket::sendVectorXd(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== by 0x401F2A: main (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== Address 0x7feffff61 is on thread 1's stack
==17043== Uninitialised value was created by a stack allocation
==17043== at 0x404BE6: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043==
==17043==
==17043== 100 errors in context 2 of 3:
==17043== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==17043== at 0x5441DA2: send (send.c:28)
==17043== by 0x404C2D: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== by 0x404E8A: unix_socket::sendVectorXd(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== by 0x401F2A: main (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== Address 0x7feffff61 is on thread 1's stack
==17043== Uninitialised value was created by a stack allocation
==17043== at 0x404BE6: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043==
==17043==
==17043== 9900 errors in context 3 of 3:
==17043== Syscall param socketcall.sendto(msg) points to uninitialised byte(s)
==17043== at 0x5441DA2: send (send.c:28)
==17043== by 0x404C2D: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== by 0x404EE8: unix_socket::sendVectorXd(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== by 0x401F2A: main (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043== Address 0x7feffff61 is on thread 1's stack
==17043== Uninitialised value was created by a stack allocation
==17043== at 0x404BE6: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client)
==17043==
==17043== ERROR SUMMARY: 10100 errors from 3 contexts (suppressed: 0 from 0)
The sendMsg(const char _type, const double _value), that the errors are pointing at, is part of unix_socket class:
//...
typedef struct{
char type;
double value;
} MESSAGE;
//...
int unix_socket::sendMsg(const char _type, const double _value){
MESSAGE msg;
msg.type=_type;
msg.value=_value;
int n = send(client_sock, &msg, sizeof(msg), 0);
if (n < 0) {
perror("send");
return -1;
}
c_sent=msg.type;
v_sent=msg.value;
return 0;
}
I don't see what is the problem. Where exactly are the uninitialized values? Or should I just ignore the errors reported by Valgrind?
Look at the MESSAGE struct:
typedef struct{
char type;
double value;
} MESSAGE;
Due to data structure alignment, value's address may be forced to align to address of a multiple of word size. Therefore, several unused bytes is padded between MESSAGE::type and MESSAGE::value. Those are the bytes which weren't initialized and thus reported by Valgrind.
As a workaround, you could force initializing the whole struct by memset().
MESSAGE msg;
memset(&msg, 0, sizeof(MESSAGE));
msg.type=_type;
msg.value=_value;
Although #timrau has described quite correctly what the core problem is here (alignment/packing), I'm not a fan of the proposed solution.
You have described a MESSAGE in your code as consisting of a char and a double. The size of the actual data structure in memory however is not sizeof(char) + sizeof(double), and that is the core problem.
The proposed solution suggests simply clearing out all of the bits of the MESSAGE structure before filling in the important bits. The problem I have with that is both a semantic one a technical one -- the size of the data structure sent down the wire is not an accurate representation of what you modeled in the code. In other words, you're not just sending a char and a double -- you're sending a char, a double and some other cruft (padding).
My suggestion is to get rid of the cruft and send only what you modeled in your code.
There is no direct support in C++ to turn off alignment and padding, but all compilers I'm aware of provide a simple mechanism to align data structures to N bytes:
#pragma pack (push, 1)
typedef struct{
char type;
double value;
} MESSAGE;
#pragma pack (pop)
This will make the MESSAGE data structure exactly what you've modeled in your code, with no padding. Doing this makes the memset unnecesarry, and you'll send exactly sizeof(char) + sizeof(double) bytes down the wire.