尝试访问库中成员的功能时的Segfault

时间:2014-04-16 14:19:39

标签: c++ segmentation-fault unique-ptr pimpl-idiom

我有一个通过谷歌测试套件彻底测试的库。我想保留它" pimpl"干净,但我遇到了一个我无法理解的段错误。

相关守则:

Interface.h:

class Interface{
public: 
Interface();
void Function(const int argument);

private:
std::unique_ptr<Implementation> Implement;    
std::unique_ptr<DependencyInjection> Injection1, Injection2;    
};

Interface.cpp:

Interface::Interface()
: Injection1(new DependencyInjection()),
Injection2(new DependencyInjection()),
Implement(new Implementation(*Injection1, *Injection2)) {}

void Interface::Function(const int argument){ Implement->Function(argument); }

Implementation.h:

class Implementation{
public: 
Implementation(AbstractInjection &injection1, AbstractInjection &injection2);
void Function(const int argument);
private:
AbstractInjection Injection1, Injection2;
};

Implementation.cpp

Implementation::Implementation(AbstractInjection &injection1, AbstractInjection &injection2)
: Injection1(injection1),
Injection2(injection2) {}

void Implementation::Function(const int argument){
injection1.Function(argument); } // code from here out is all well tested and works 

因此,当我创建接口并调用Interface.Function()时,代码会在尝试评估Implementation.Function()时发生段错误。我通过我能想到的一切运行gdb,所有指针都是非空的。

如果我只是创建一个看起来像

的测试
std::unique_ptr<DependencyInjection1> injection1(new DependencyInjection());
std::unique_ptr<DependencyInjection2> injection2(new DependencyInjection());
std::unique_ptr<Implementation> implement(new Implementation(*injection1, *injection2));
implement->Function(0);

代码工作正常,不会出现段错误

但是如果我创建像

这样的测试
Interface iface;
iface.Function(0);

它将是段错误。

我是整个unique_ptr的新手,但我怀疑这不是更大的问题。它可能是红鲱鱼,我不知道。

2 个答案:

答案 0 :(得分:1)

问题实际上应该像警告一样弹出。

初始化程序按它们出现在类定义中的顺序完成,而不是它们出现在构造函数中的顺序!

切换到:

class Interface{
public: 
Interface();
void Function(const int argument);

private:
std::unique_ptr<DependencyInjection> Injection1, Injection2;
std::unique_ptr<Implementation> Implement;

};

从这里开始:C++: Initialization Order of Class Data Members,这是C ++标准&#34; 12.6.2&#34;

答案 1 :(得分:1)

你的成员字段顺序错误,它们是按照在类中声明的顺序初始化的。因此,在implement之前初始化injections。使用-Werror=reorder来获取编译器错误(对于GCC和可能是CLang)