c++ 对只读部分“.text”中的xxx进行重定位-SUSE中的编译器或linux设置错误?

2ledvvac  于 2022-11-19  发布在  Linux
关注(0)|答案(4)|浏览(101)

我不是Linux的常客,我想我做错了什么。
这是我正在生成的测试动态库“.so”的代码。

class InternalClass
{
public:
    int Function(){ return 10; }
};

extern "C"
{
    int WrapperFunctionSimple() { return 10; }
    void WrapperCreateInstance() {InternalClass* item = new InternalClass(); delete item; }
}

编译失败,并出现以下错误:

g++ -Wall -fexceptions -O2  -c /home/lidia/compartida/TestLibrary/TestLibrary/main.cpp -o obj/Release/main.o
g++ -shared  obj/Release/main.o  -o bin/Release/libTestLibrary.so -s  
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: obj/Release/main.o: warning: relocation against `_Znwm@@GLIBCXX_3.4' in read-only section `.text'
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: obj/Release/main.o: relocation R_X86_64_PC32 against symbol `_Znwm@@GLIBCXX_3.4' can not be used when making a shared object; recompile with -fPIC
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status

我按照建议尝试使用-fPIC,它可以编译。但是当使用这个库时,当我添加最后一个函数时,它不能被加载:

void WrapperCreateInstance() {InternalClass* item = new InternalClass(); delete item; }

问题是使用InternalClass,没有这个函数一切都正常。
我用的是VirtualBox。我安装了64位的OpenSUSE,使用这个库的应用程序也是64位的。在另一个linux发行版(Mint)中,使用完全相同的项目和设置(没有fPIC),它可以被编译。当我使用那个库(.so)时,它在SUSE中工作。
我还使用:

  • gcc(SUSE Linux)7.5.0版
  • g++(SUSE Linux)7.5.0版中的一个版本
  • 我的IDE是Code::Blocks 20(最新版本)。除了-m64标志外,其他设置均为空。

我做错了什么?这似乎是高级Linux用户可以帮助我理解的东西。
编辑:要添加更多信息,可以使用相同的设置在Ubuntu中编译。

nbysray5

nbysray51#

对我来说,如果一个库(A)依赖于另一个库(B),并且库A在库B之前被链接,那么这种情况就发生了。解决方案是先链接库B,然后链接库A。

x6492ojm

x6492ojm2#

当我使用GCC编译CPP文件时,我也遇到过这种情况。因此,对于C文件,只使用g,而显然不使用GCC,因为GCC是针对C文件的。

fdx2calv

fdx2calv3#

我在ubuntu中使用cmake和GCC,我得到了同样的错误。
在我的例子中,我添加了XX. h文件来包含目录,并在main.cpp中使用了一个在XX. h头文件中定义的“typedef struct x”。
当我在Cmake的add_executable()中将XX. c添加到目标可执行源代码时,这个错误被清除。
我希望我能清楚地陈述我的情况。

de90aj5v

de90aj5v4#

在我的例子中,当我有一个抽象类A和两个派生类B和C时,就发生了这种情况,如下所示。

class BaseAbstractClass
{
public:
    virtual void doNothing(void) = 0;
};

class A : public BaseAbstractClass
{
public:
    void doNothing(void){
        return;
    }
};

class B : public BaseAbstractClass
{
public:
    void doNothing(void);    // Only declaration, definition is nowhere
};

但是其中一个派生类(此处为class B)只有doNothing()的声明,但在项目文件中的任何位置都缺少定义。

相关问题