来自共享库的 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
环境信息
- OS: macOS 10.11.6 (El Capitan)
- 编译器: Apple LLVM 版本 8.0.0 (clang-800.0.42.1) (g++ links to this)
- 链接器:ld
我尝试过的事情
我已经做了这些事情来试图缩小原因,特别是由于 subclass 是一个模板,而 base class 来自共享库。
确保 BaseClass 可以被自己引用。
通过将 main.cpp
更改为包含 BaseClass
并在 main()
中实例化并在其上调用 foo()
来对此进行测试。编译和 linked 没有错误。
从内部库派生 class 而不是来自共享库。
通过创建一个名为 InternalBaseClass
的 class 进行测试,其来源完全相同,除了定义文件中的 __attribute__
行,将其包含在 DerivedClass
header 中包含 BaseClass
的位置,并将其指定为 DerivedClass
的 class 声明中的 parent。编译和 linked 没有错误。
制作DerivedClass
non-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.
总结
我构建了一个包含 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
环境信息
- OS: macOS 10.11.6 (El Capitan)
- 编译器: Apple LLVM 版本 8.0.0 (clang-800.0.42.1) (g++ links to this)
- 链接器:ld
我尝试过的事情
我已经做了这些事情来试图缩小原因,特别是由于 subclass 是一个模板,而 base class 来自共享库。
确保 BaseClass 可以被自己引用。 通过将
main.cpp
更改为包含BaseClass
并在main()
中实例化并在其上调用foo()
来对此进行测试。编译和 linked 没有错误。从内部库派生 class 而不是来自共享库。 通过创建一个名为
InternalBaseClass
的 class 进行测试,其来源完全相同,除了定义文件中的__attribute__
行,将其包含在DerivedClass
header 中包含BaseClass
的位置,并将其指定为DerivedClass
的 class 声明中的 parent。编译和 linked 没有错误。制作
DerivedClass
non-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.