【问题标题】:How to make linker fail for undefined references when building shared library in Linux在 Linux 中构建共享库时如何使链接器因未定义的引用而失败
【发布时间】:2020-04-11 11:10:03
【问题描述】:

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

此示例中的细节可能有点过多,但我不完全确定如何减少它并使其具有代表性。

Base.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;
}
}

派生的.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();
}

OtherClass.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

【问题讨论】:

  • 当然没问题。运行任何工具进行共享对象检查,您会发现该符号将被标记为运行时依赖项。 ldd libtest_dll.so 应该显示依赖关系。
  • @0andriy 这个想法是OtherClass::bar() 应该在这个源代码中,但是我不小心把它漏掉了。我不想在运行时找到它,而是想在编译时找到它。

标签: c++ linux linker shared-libraries


【解决方案1】:

当我正在构建并希望避免这种情况时,我使用以下选项编译库:-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

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

【讨论】:

  • 太棒了! -Wl,-z,defs 解决了这个问题,尽管我认为-Wl,--no-allow-shlib-undefined 不会影响您的示例或我的示例。此外,看起来-Wl,--no-undefined-Wl,z,defs 相同。知道要搜索的正确关键字将我指向this question,其中我的可能是重复的。
猜你喜欢
  • 2017-03-15
  • 1970-01-01
  • 2019-02-12
  • 1970-01-01
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多