如何在 Linux 中构建共享库时使未定义引用的链接器失败

How to make linker fail for undefined references when building shared library in Linux

本文关键字:引用 未定义 链接 失败 Linux 共享 构建      更新时间:2023-10-16

我正在尝试在 Ubuntu 中以 C++ 构建一个共享库(我将在运行时使用dlopen加载(,但我注意到即使缺少一些依赖项,共享库也能很好地构建。如果我要构建一个可执行文件,我会得到一个undefined reference链接器错误,这就是我希望在这里看到的。

这个例子中可能有太多的细节,但我不完全确定如何削减它并使其具有代表性。

基数.h

class Base{
public:
virtual void foo()=0;
};
extern "C" {
Base* CreateBase();
}
extern "C" {
void DestroyBase(Base* b);
}

派生.h

#include "Base.h"
class Derived : public Base {
public:
void foo();
};
extern "C" {
Base* CreateBase() {
return new Derived;
}
}
extern "C" {
void DestroyBase(Base* b) {
delete b;
}
}

Derived.cc

#include "Derived.h"
#include "OtherClass.h"
#include <iostream>
void Derived::foo(){
std::cout << "Derived::foo()" << std::endl;
std::cout << "Calling OtherClass::bar()" << std::endl;
OtherClass other;
other.bar();
}

其他类.h

class OtherClass{
public:
void bar();
};

我构建共享库的命令行是

g++ -shared -fPIC -o libtest_dll.so Derived.cc

问题是我没有定义Derived::foo()调用的OtherClass::bar(),但libtest_dll.so构建时没有错误或警告。我的理解是,在Windows的Visual Studio中,如果我用这段代码构建一个DLL,它将无法链接。如何在 Ubuntu/Linux 中使用g++获得这种行为?

在 Ubuntu 19.04 上运行 g++ 8.3.0-6

当我构建并希望避免这种情况时,我使用以下选项编译库:-Wl,--no-allow-shlib-undefined -Wl,-z,defs

第一个选项会导致共享库的链接在代码中未定义符号的情况下失败,当与第二个选项结合使用时,这会导致链接器报告缺少的符号。

这可以通过在链接时检测符号来很好地防止运行时丢失符号。但是,我确实需要将.so与其使用的所有库链接起来,否则将无法构建。

样品 (src.c(:

#include <math.h>
extern
double share_the_stuff(double val)
{
return acos(val * val);
}

使用缺少的符号构建:

gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs
/usr/bin/ld: /tmp/ccFmD5uY.o: in function `share_the_stuff':
src.c:(.text+0x17): undefined reference to `acos'
collect2: error: ld returned 1 exit status

libm.so 中的链接:

gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs -lm

它的行为与缺少内部符号的行为相同。