繁体   English   中英

共享库中非模板库的模板子类导致“类”链接错误导致未定义符号typeinfo

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

摘要

我建立了一个共享库,其中包含一个非模板类,从该类我可以在链接到该库的项目中派生一个模板类。

当我编译/链接引用项目时,收到以下链接错误:

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

typeinfo实际上指的是什么? 我很难找到有关它的信息,以便进行更深入的研究。

该错误几乎暗示着期望BaseClass具有某种类型的信息,但是我不明白缺少了什么。

另外,我知道此错误通常伴随vtable for ...链接错误,通常是在您忘记为虚拟方法提供定义或将其定义为纯虚拟方法的情况下,但是我相信我已将事物排除为#1 我在下面尝试过 ,因为如果无法从库中获取foo()的定义,则main.cpp将无法编译。

资源

我将类简化为以下类,这些类仍然可以重现该问题:

BaseClass.h (我链接的共享库的一部分)

#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 (在与库链接的单独项目中)

#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

环境信息

  • 作业系统: macOS 10.11.6(El Capitan)
  • 编译器: Apple LLVM版本8.0.0(clang-800.0.42.1)(与此相关的g ++链接)
  • 连结器: ld

我尝试过的事情

我已经做了这些事情,以试图将原因归因于具体是由于子类是模板,而基类来自共享库。

  1. 确保BaseClass可以单独引用。 通过将main.cpp更改为包括BaseClass ,并在main()实例化它,并在其上调用foo()进行了测试。 编译和链接没有错误。

  2. 从内部基类派生,而不是从共享库派生。 通过创建一个名为InternalBaseClass的类来进行测试,该类具有完全相同的源,但定义文件中的__attribute__行除外,并将其包括在DerivedClass头文件中,而不是包括BaseClass在内,并将其指定为DerivedClass的类声明中的父级。 编译和链接没有错误。

  3. 使DerivedClass非模板。 通过删除DerivedClass模板声明并将对参数化类型T引用替换为int 这将编译并链接没有错误。

提前致谢!

似乎您正在使用“ -fvisibility = hidden”构建共享库,并使用__attribute__((visibility("default")))标记导出的函数,但是,要导出RTTI,您需要使用__attribute__((visibility("default"))) gcc referece

请注意,类型可见性应用于与类关联的模糊链接实体(vtable,typeinfo节点等)。 尤其是,如果将一个类作为异常抛出到一个共享库中并被另一个共享库捕获,则该类必须具有默认可见性。 否则,两个共享库将无法使用相同的typeinfo节点,并且异常处理将中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM