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.
Related
I'm testing c++17 shared_ptr to see how it handles array delete[], but it failed expectation.
First, c++17 document says shared_ptr<T[]> can handle delete[] properly.
http://eel.is/c++draft/util.smartptr.shared#const-5
Effects: When T is not an array type, constructs a shared_ptr object that owns the pointer p. Otherwise, constructs a shared_ptr that owns p and a deleter of an unspecified type that calls delete[] p.
And reset():
http://eel.is/c++draft/util.smartptr.shared#mod-3
Equivalent to shared_ptr(p).swap(*this).
It will transfer the specification-required custom delete. So from my understanding, pre-c++17 I have to write like this:
shared_ptr<int> t1(new int[7], default_delete<int[]>());
Now it knows when 1st parameter is array type, compiler will generate call to delete [], so that we no longer have to specify delete function explicitly. I had a quick test on Ubuntu20.04 with clang++13:
int main() {
shared_ptr<int> t1(new int[7], default_delete<int[]>());
return 0;
}
Then clang++ mytest.cpp && valgrind ./a.out, no problem. But if I change to:
int main() {
shared_ptr<int> t1(new int[7]);
return 0;
}
Then clang++ mytest.cpp -std=c++17 && valgrind ./a.out will print:
==16407== Command: ./a.out
==16407==
Father
1
==16407== Mismatched free() / delete / delete []
==16407== at 0x483CFBF: operator delete(void*) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==16407== by 0x40450A: std::_Sp_counted_ptr<int*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (in /home/troskyv/a.out)
==16407== by 0x4030A2: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (in /home/troskyv/a.out)
==16407== by 0x403059: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (in /home/troskyv/a.out)
==16407== by 0x403998: std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (in /home/troskyv/a.out)
==16407== by 0x4020C4: std::shared_ptr<int>::~shared_ptr() (in /home/troskyv/a.out)
==16407== by 0x40152E: main (in /home/troskyv/a.out)
==16407== Address 0x4db34c0 is 0 bytes inside a block of size 28 alloc'd
==16407== at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==16407== by 0x4014F7: main (in /home/troskyv/a.out)
==16407==
==16407==
==16407== HEAP SUMMARY:
==16407== in use at exit: 0 bytes in 0 blocks
==16407== total heap usage: 15 allocs, 15 frees, 74,032 bytes allocated
==16407==
==16407== All heap blocks were freed -- no leaks are possible
==16407==
==16407== For lists of detected and suppressed errors, rerun with: -s
==16407== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
There's memory leak. So seems to me although I used -std=c++17 option, shared_ptr still cannot handle delete array automatically.
Where did this get wrong?
I see the answer is difference between shared_ptr<int> and shared_ptr<int[]>. Use of the latter one avoids memory leak.
Thanks, close this question!
I've tried to change the code to do what I want in different ways but doesn't seem to fix that Valgrind error.
Cadena::Cadena(unsigned tam, char c):s_(new char[tam+1]), tam_(tam)
{
//c is ' ' by default
memset(s_, c, tam+1);
s_[tam]='\0';
}
...
Cadena& Cadena::substr(unsigned i, unsigned tam) const
{
if(i>=tam_||i+tam>tam_) throw out_of_range("Posicion indicada fuera de rango");
Cadena* subCad=new Cadena(tam);
strncpy(subCad->s_, &s_[i], tam);
return *subCad;
}
==9669== Invalid write of size 1
==9669== at 0x1390CC: Cadena::Cadena(unsigned int, char) (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== by 0x13972B: Cadena::substr(unsigned int, unsigned int) const (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== by 0x12D436: test_cadena(_fctkern_t*) (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== by 0x137D42: main (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== Address 0x105bc176f is not stack'd, malloc'd or (recently) free'd
==9669==
==9669==
==9669== Process terminating with default action of signal 11 (SIGSEGV)
==9669== Access not within mapped region at address 0x105BC176F
==9669== at 0x1390CC: Cadena::Cadena(unsigned int, char) (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== by 0x13972B: Cadena::substr(unsigned int, unsigned int) const (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== by 0x12D436: test_cadena(_fctkern_t*) (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== by 0x137D42: main (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==9669== If you believe this happened as a result of a stack
==9669== overflow in your program's main thread (unlikely but
==9669== possible), you can try to increase the size of the
==9669== main thread stack using the --main-stacksize= flag.
==9669== The main thread stack size used in this run was 8388608.
Another way:
Cadena& Cadena::substr(unsigned i, unsigned tam) const
{
if(i>=tam_||i+tam>tam_) throw out_of_range("Posicion indicada fuera de rango");
char res[tam+1];
strncpy(res, s_+i, tam);
res[tam]='\0';
Cadena* subCad=new Cadena(tam);
return *subCad;
}
==17029== Invalid write of size 1
==17029== at 0x4C3304C: strncpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17029== by 0x13979E: Cadena::substr(unsigned int, unsigned int) const (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==17029== Address 0x1fff001000 is not stack'd, malloc'd or (recently) free'd
==17029==
==17029==
==17029== Process terminating with default action of signal 11 (SIGSEGV)
==17029== Access not within mapped region at address 0x1FFF001000
==17029== at 0x4C3304C: strncpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17029== by 0x13979E: Cadena::substr(unsigned int, unsigned int) const (in /mnt/hgfs/mvpoosf/P1/test-P1-auto)
==17029== If you believe this happened as a result of a stack
==17029== overflow in your program's main thread (unlikely but
==17029== possible), you can try to increase the size of the
==17029== main thread stack using the --main-stacksize= flag.
==17029== The main thread stack size used in this run was 8388608.
I'm passing this test (test-P1-auto):
FCT_TEST_BGN(Cadena - Subcadena: tamanno mayor que longitud restante) {
const Cadena a("0123456789");
fct_chk_ex(out_of_range&, a.substr(9, 2));
}
FCT_TEST_END();
It returns a substring of two elements following the number 8. It's not possible as it throws out_of_range, so the test is OK. But when I use Valgrind, it's giving me those errors and I've been stuck here for hours.
Private part of my class Cadena:
private:
char* s_;
unsigned int tam_;
Sorry for the mistake guys, but as #Some programmer dude commented I didn't put the flag -g on my makefile that allows valgrind to tell me wich lines make the errors. Actually that wasn't the right test, it was the next one:
FCT_TEST_BGN(Cadena - Subcadena: tamanno negativo) {
const Cadena a("0123456789");
fct_chk_ex(out_of_range&, a.substr(9, -1));
}
FCT_TEST_END();
As I can see here Signed to unsigned conversion in C - is it always safe?, there's no way to get a negative value as unsigned and expect the sign "just to be removed". I solved it by changing it to int and checking inside the function if it's negative.
Thanks everyone for your help.
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).
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);?
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.