This is a follow up on one of my previous questions. The issue that I am dealing with is explained in detail in the formulation of the aforementioned question. Unfortunately, I was not able to provide a minimal example that showcases the problem.
In this question, I am making an attempt to redefine the problem and provide a minimal example. The code presented in the example below executes and does what it is supposed to do. However, in a slightly more complex case presented in the previous question, sometimes, it results in the runtime error
dynamic_links(3941,0x7fff749a2310) malloc: *** error for object 0x61636f6c65720054: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Unfortunately, I was only able to produce the error when the optimisation is set to -O3 (possibly -O2 as well). This creates a problem when using debugging tools. Unfortunately, I was not able to reproduce the problem with no/minimal code optimisation. For a reference, I am using gcc 4.9.1.
In the present question, I would like to understand if the structural design of the class inheritance mechanism that I am using could, potentially, be dangerous from the perspective of the dynamic memory allocation. Please find the code below:
namespace ublas = boost::numeric::ublas;
template<typename TScalarType = double>
using ublasRn = ublas::vector<TScalarType>;
class Base
{
public:
virtual ~Base(void) = 0;
};
Base::~Base(void){}
template<typename T1, typename T2>
class Composite : public Base
{
protected:
T1 T1Instance;
std::unique_ptr<T2> u_T2Instance;
public:
Composite(){}
virtual ~Composite(void){}
const std::type_info& returnT1TypeID(void) const
{return typeid(T1);}
const std::type_info& returnT2TypeID(void) const
{return typeid(T2);}
};
template<typename T2>
class CompositeCT: virtual public Composite<double, T2>
{
public:
using Composite<double, T2>::Composite;
virtual ~CompositeCT(void)
{}
};
template<typename T1>
class CompositeRn: virtual public Composite<T1, ublasRn<double>>
{
public:
using Composite<T1, ublasRn<double>>::Composite;
virtual ~CompositeRn(void){}
};
class CompositeCTRn :
public CompositeCT<ublasRn<double>>,
public CompositeRn<double>
{
public:
CompositeCTRn(void):
Composite<double, ublasRn<double>>(),
CompositeCT<ublasRn<double>>(),
CompositeRn<double>()
{};
};
template<typename T1, typename T2, class TComposite>
class Trajectory: public Base
{
protected:
std::vector<std::unique_ptr<TComposite>> m_Trajectory;
public:
Trajectory(void)
{checkType();}
void checkType(void) const
{
TComposite CI;
if (
!(
CI.returnT1TypeID() == typeid(T1) &&
CI.returnT2TypeID() == typeid(T2)
)
)
throw std::runtime_error("Error");
}
virtual ~Trajectory(void){}
};
int main()
{
Trajectory<
double,
ublasRn<>,
CompositeCTRn
> T;
std::cout << 123 << std::endl;
}
Note. I am using the external library boost::ublas. I believe that it is not unlikely that the problem is related to the dynamic memory allocation mechanism for the ublas objects.
Well. I'm thinking you're really pushing the type system. I cannot begin to fathom why you would want this egregious type hierarchy:
That's a lot of damage done in ~60 lines of code. I cannot think of a reasonable situation where Liskov Substitution Principle holds for this hierarchy.
Especially this line (declaring the center of the diagram, essentially):
This effectively declares a class with a single virtual base, which is "aliased" via three bases:
This means there should be only one
_i1and one_i2member in the type. That means that on all conforming compilers, the following should compile and run without triggering any asserts or causing memory leaks etc.:In fact, that's exactly what happens on gcc 4.8, 4.9, 5.0 and clang++ 3.5.
Live On Coliru
Under valgrind:
No problem at all.
Notes
I replaced the type check with a static assert (because, why not?!)
Summary / TL;DR
I've looked at your code. Other than a nice bouquet of design smells I don't see anything wrong with it, really. If you need more help, you'll have to start being specific about versions, flags, compilers, architecture...