动态共享库中的虚函数会产生段错误

C++: Virtual functions in dynamic shared library produce segfault

本文关键字:段错误 错误 共享 函数 动态      更新时间:2023-10-16

在我正在编写的应用程序中,我正在从我编写的共享库中动态加载对象。

在虚函数发挥作用的情况下,这一点很好。这意味着我可以很容易地调用getter和setter,但是当我试图调用覆盖虚拟基类函数的函数时,我立即得到一个分段错误。我现在已经没有想法了,因为这发生在我的项目中的每个类(层次结构)。

这些函数可以在应用程序内部创建对象时成功调用,根本不需要使用动态加载或共享库。

我怀疑要么是概念上的错误,要么是我这边的编译/链接错误。

类的层次结构看起来像这样:

BaseClass.h:

class BaseClass : public EvenMoreBaseClass { public: virtual bool enroll(const shared_ptr<string> filepath) = 0; }

Derived.h:

class Derived : public BaseClass { bool enroll(const shared_ptr<string> filepath); }

Derived.cpp:

bool Derived::enroll(const shared_ptr<string> filepath) { cout << "enroll" << endl; }

(包括这里遗漏的名称空间)

应用程序加载库并获得一个(共享的)指向BaseClass对象的指针(应用程序包含BaseClass.h)。所有函数都可以执行,除了虚函数。

开发在Eclipse CDT中完成。当前,所有内容都在一个项目中,具有不同的构建配置(应用程序的.cpp在共享库的配置中被禁用,反之亦然)。编译器是g++ 4.4。所有层次结构的。o文件都与库链接,设置-shared。

也许这是一个很晚的答案,但我发现相同的行为,如果您在访问虚拟方法之前使用dlclose(handle)(尽管静态方法正常工作),则会发生这种情况。所以你不应该关闭库句柄,直到你完成了它的对象。

确保dll和可执行文件都使用完全相同的编译器设置进行编译。如果它们不同,编译器可能会在可执行文件中生成与dll期望的不匹配的代码,反之亦然,这是ODR冲突。

请注意,标准库类型,如std::string和std::shared_ptr,在调试配置中可能有不同的布局,并且在不同的编译器版本之间也可能发生变化(即使来自同一供应商)。

一般来说,你需要小心使用跨dll边界的类。通常建议只处理内置类型和无状态接口。

在构建配置中设置的项目之间的类型大小是否有任何差异?

(更新)

我遇到过类似的问题,当一个项目有类型,如短和长定义为不同的大小到另一个项目,并通过相同的头文件引用包含这些类型的类。一个项目把第二个短字符放在第2字节处,另一个项目认为它在第4字节处。

我也有不同的填充值的问题。一个项目将奇数字符填充到4字节边界,另一个项目认为它填充到8字节边界。

对于虚函数指针也是如此,可能一个项目将它们放入32位,另一个项目将它们放入64位。