vendredi 27 mars 2015

c++ Polymorphism : segfault and reference strange behaviour

Here is a MWE that, when compiled with g++ -std=c++11, produces a segmentation fault:



#include <iostream>
#include <random>

class Rand{
public:
Rand(double const& min_inclusive, double const& max_exclusive):
mt_(std::random_device()()),
dist_(min_inclusive,max_exclusive){}
~Rand(){}
double get() { return dist_(mt_); }
private:
std::mt19937_64 mt_;
std::uniform_real_distribution<double> dist_;
};

class Base {
public:
Base():rnd(0.0,1.0){ std::cout<<"Base created "<<&rnd<<" "<<rnd.get()<<std::endl; }
virtual ~Base(){};
Rand rnd;
};

class Child: public Base{
public:
Child():var(1.0){ std::cout<<"Child created"<<std::endl; }
double var;
};

class Other {
public:
Other(Base* b):b(b){ std::cout<<"Other created "<<&(b[0].rnd)<<" and "<<&(b[1].rnd)<<"--->"<<b[0].rnd.get()<<" "<<b[1].rnd.get()<<std::endl; }
Base* b;
};

int main(){
unsigned int N(2);
std::cout<<"#############"<<std::endl;
Base* b(new Base[N]);
Other o1(b);
std::cout<<"#############"<<std::endl;
Child* c(new Child[N]);
Other o2(c);
std::cout<<"#############"<<std::endl;
delete[] b;
delete[] c;
}


The typical output is :



#############
Base created 0x239c020 0.226514
Base created 0x239ca00 0.902337
Other created 0x239c020 and 0x239ca00--->0.864321 0.302185
#############
Base created 0x239d3f0 0.573563
Child created
Base created 0x239ddd8 0.422187
Child created
Other created 0x239d3f0 and 0x239ddd0--->0.909183 4.94066e-324
#############


In the first part where a Base class is given to Other the references are coherent and the code runs properly.


But when a Child class is given to Other, the first reference is identical but the second is slightly different. The direct consequence of that is that the b[1].rdn.get() is always (very close) '0'. The other indirect consequence is that the code ends with a SegFault...


Moreover, when Child::var is absent, the program works fine, all references are coherent and there is no SegFault.


What am I doing wrong ? Is it impossible to create Other with a child of Base ? If so, it looks like the polymorphism is ruined...


Aucun commentaire:

Enregistrer un commentaire