来自共享库的 non-template 基类的模板子类导致 'class' link 错误的未定义符号类型信息

Template subclass of non-template base from shared library causing Undefined symbols typeinfo for 'class' link error

总结

我构建了一个包含 non-template class 的共享库,我从中派生了项目中的模板 class linked 到图书馆。

当我 compile/link 引用项目时,我收到以下 link 错误:

Undefined symbols for architecture x86_64:
  "typeinfo for BaseClass", referenced from:
      typeinfo for DerivedClass<int> in main.o

typeinfo实际指的是什么?我很难找到有关它的信息,以便更深入地挖掘。

该错误似乎暗示 BaseClass 应该具有某种类型的信息,但我不明白缺少什么。

此外,我知道此错误通常伴随 vtable for ... link 错误,通常是在您忘记为虚拟方法提供定义或将其定义为纯虚拟时,但我相信我'我已经用下面 我试过的事情 中的 #1 排除了这一点,因为如果库中没有 foo() 的定义,main.cpp 将无法编译.

来源

我已经将 classes 提炼为以下仍然重现问题的内容:

BaseClass.h(我link反对的共享库的一部分)

#ifndef BASECLASS_H_
#define BASECLASS_H_

class BaseClass
{
    protected:
        int myField;

    public:
        BaseClass();
        virtual ~BaseClass() {}

        virtual void foo();
};

#endif

BaseClass.cpp(编译成生成的dylib)

#include <iostream>
#include "BaseClass.h"

__attribute__((visibility("default")))
BaseClass::BaseClass()
    : myField(0)
{

}

__attribute__((visibility("default")))
void BaseClass::foo()
{
    std::cout<<myField<<std::endl;
}

DerivedClass.h(在针对库 link 的单独项目中)

#ifndef DERIVEDCLASS_H_
#define DERIVEDCLASS_H_

#include <BaseClass.h>

template <typename T>
class DerivedClass : public BaseClass
{
    protected:
        T data;

    public:
        DerivedClass(T data) : data(data) {}
        virtual ~DerivedClass() {}
};

#endif

main.cpp(引用DerivedClass表示有问题)

#include "DerivedClass.h"

int main()
{

    DerivedClass<int> derived(0);
    derived.foo();

    return 0;
}

构建命令

共享库

编译:

g++ -O3 -Wall -c -fmessage-length=0 -fvisibility=hidden -MMD -MP -MF"src/BaseClass.d" -MT"src/BaseClass.o" -o "src/BaseClass.o" "../src/BaseClass.cpp"

链接:

g++ -Xlinker -install_name -Xlinker "@rpath/libmylibrary.dylib" -dynamiclib -o "libmylibrary.dylib" ./src/BaseClass.o

引用项目

编译:

g++ -I"/code/myproject/deps/mylibrary/include" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/main.d" -MT"src/main.o" -o "src/main.o" "../src/main.cpp"

链接:

g++ -L"/code/myproject/deps/mylibrary/bin" -Xlinker -rpath -Xlinker "@loader_path" -o "myproject"  ./src/InternalBaseClass.o ./src/main.o   -lmylibrary

环境信息

我尝试过的事情

我已经做了这些事情来试图缩小原因,特别是由于 subclass 是一个模板,而 base class 来自共享库。

  1. 确保 BaseClass 可以被自己引用。 通过将 main.cpp 更改为包含 BaseClass 并在 main() 中实例化并在其上调用 foo() 来对此进行测试。编译和 linked 没有错误。

  2. 从内部库派生 class 而不是来自共享库。 通过创建一个名为 InternalBaseClass 的 class 进行测试,其来源完全相同,除了定义文件中的 __attribute__ 行,将其包含在 DerivedClass header 中包含 BaseClass 的位置,并将其指定为 DerivedClass 的 class 声明中的 parent。编译和 linked 没有错误。

  3. 制作DerivedClassnon-template. 通过删除 DerivedClass 中的模板声明并将对参数化类型 T 的引用替换为 int 来对此进行测试。这编译 & links 没有错误。

提前致谢!

看起来您正在使用“-fvisibility=hidden”构建共享库并使用 __attribute__((visibility("default"))) 标记导出的函数,但是为了导出 RTTI,您需要使用 [= 标记导出的 class 10=]。来自 gcc referece:

Note that the type visibility is applied to vague linkage entities associated with the class (vtable, typeinfo node, etc.). In particular, if a class is thrown as an exception in one shared object and caught in another, the class must have default visibility. Otherwise the two shared objects are unable to use the same typeinfo node and exception handling will break.