使用 extern 时 gcc 的重定位错误

Posted

技术标签:

【中文标题】使用 extern 时 gcc 的重定位错误【英文标题】:Relocation error with gcc when using extern 【发布时间】:2016-06-26 11:16:23 【问题描述】:

我收到以下代码的重定位错误。请有人帮我解决这个问题。

A.hpp

namespace

class A

    public:
        A(const std::string&);
        //Few Get() methods
    private:
        //Some private stuff
;
    extern A objA;

A.cpp

#include<A.hpp>

const std::string str("FIXED STRING HERE");
A objA(str);

A::A(const std::string& Istring)

    //Some data processing here

ClientCode.cpp

#include<A.hpp>



// Want to access A::get() here using objA;
objA.Get();

我收到以下错误:

重定位R_X86_64_PC32 对未定义符号`(匿名命名空间)::str' 在制作共享对象时不能使用;使用 -fPIC 重新编译 最终链接失败:错误值 collect2: ld 返回 1 个退出状态

另外,请有人知道这个外部对象的内存是什么时候分配的。 我的主要目的是只拥有 A 类的单个对象,并在我包含 A.hpp 时在许多文件中使用它

【问题讨论】:

【参考方案1】:

A.hpp

namespace ABC

    class A
    
        public:
            A(const std::string&);
            //Few Get() methods
        private:
            //Some private stuff
    ;
  extern A objA;

A.cpp

#include<A.hpp>
namespace ABC

     const std::string str("FIXED STRING HERE");
      A objA(str);

      A::A(const std::string& Istring)
      
         //Some data processing here
      

客户端代码.cpp

#include<A.hpp>
// Want to access A::get() here using objA;
ABC::objA.Get();

【讨论】:

【参考方案2】:

使用externClientCode.cpp 中的strobjA 显式声明为从其他cpp 源文件编译的其他目标文件定义的待链接符号。

#include<A.hpp>

extern const std::string str;
extern A objA;

// Want to access A::get() here using objA;
objA.Get();

============ 编辑

同时删除A.hpp中的extern语句

namespace

class A

    public:
        A(const std::string&);
        //Few Get() methods
    private:
        //Some private stuff
;
    //extern A objA;

【讨论】:

你的意思是我让 A.cpp 中的代码保持原样? const std::string str("这里的固定字符串");一个 objA(str); @user3836455 是的。全局类初始化将在 main() 条目执行之前进行。 抱歉,它不起作用。错误返回“错误:对'objA'的引用不明确” @user3836455 objA.Get(); 应该在一个非全局函数中。 是的,它不是全局的,它在函数内部【参考方案3】:

重定位错误可能是由于“匿名”命名空间造成的。您必须为命名空间分配一个名称。

至于何时为外部对象标识符分配内存,是在调用对象构造函数时。将对象标识符声明为外部具有向编译器指示标识符可以在多个文件中使用的效果,因此在链接时,包含该标识符的所有文件都指向同一个对象。

显然,实例化(何时何地)取决于程序员,他们有责任正确地执行它以避免对象未实例化错误,一种空引用错误。

【讨论】:

以上是关于使用 extern 时 gcc 的重定位错误的主要内容,如果未能解决你的问题,请参考以下文章

图片+代码:GCC 链接过程中的重定位过程分析.md

图片+代码:GCC 链接过程中的重定位过程分析.md

运行时 gcc 重定位错误

“kernelUD 中的错误:至少需要 5 次重定位才能适应主范围”,但每组的重定位数超过 5 次

从linux到openwrt的交叉编译时,通用ELF(EM:62)中的重定位

PE知识复习之PE的重定位表