I am trying to solve valgrind errors in a code, but I am having some trouble… Perhaps someone can give me some hints ?
I have a "Mother" class holding a whole lot of attributes "A, B, C, D, ..." that are all references to objects of the same type (i.e. "SomeClass &")
Code:
class Mother
{
//
public:
//
Mother(foo, bar);
//
private:
//
SomeClass & A;
SomeClass & B;
SomeClass & C;
SomeClass & D;
etc.
};
Each attribute is constructed within the initialisation list of the Mother() constructor :
Code:
Mother::Mother(foo, bar)
: A (*new SomeClass(foo, bar, "alpha"))
, B (*new SomeClass(foo, bar, "beta" ))
, C (*new SomeClass(foo, bar, "gamma"))
, D (*new SomeClass(foo, bar, "zeta" ))
, etc.
The valgrind error occurs after around 50 such references to objects have been initialised and 4 still need to be initialised. The error is of the form :
Code:
==8347== Invalid write of size 8
==8347== at 0x42776B: Mother::Mother([...]) (mother.cpp:[...])
==8347== by [...]
==8347== Address 0x9081fe8 is 0 bytes after a block of size 440 alloc'd
==8347== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8347== by [...]
I've tried to run gdb along with valgrind, but gdb gets lost in the code : it thinks it is at some place that is inconsistent with what "std::cout << [...]" instructions print on the screen.
As an alternative, I've added "std::cout << [...]" instructions in the code to locate where the valgrind message occurs. Unfortunately, it occurs after the "std::cout [...]" instruction located at the last line of the SomeClass() constructor and before the first "std::cout [...]" instruction located within the first initialiser list item of the next SomeClass object.
Code:
static dummy([...])
{
std::cout << "first" << std::endl;
return [...]
}
SomeClass::SomeClass(foo, bar)
: A ( dummy( *new SomeClass(foo, bar) ) )
, B (*new SomeClass(foo, bar))
, C (*new SomeClass(foo, bar))
, D (*new SomeClass(foo, bar))
, etc.
{
[...]
std::cout << "last" << std::endl;
}
Swapping the order of two attributes does not change the error.
I.e. if the valgrind error occurs after constructing C and before constructing D then the following code
Code:
Mother::Mother(foo, bar)
: A (*new SomeClass(foo, bar))
, B (*new SomeClass(foo, bar))
, D (*new SomeClass(foo, bar))
, C (*new SomeClass(foo, bar))
, etc.
Will show an error after constructing D and before constructing C.
From your experience, would you have any idea/hint regarding what could cause the Valgrind error ? What I should try to do to find the root cause ? Is there is a better way to write my code ?