簡體   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