【问题标题】:nm reports symbol is defined but ldd reports symbol is undefinednm 报告符号已定义,但 ldd 报告符号未定义
【发布时间】:2009-06-03 02:01:47
【问题描述】:

我遇到了链接问题。我需要链接一个共享库libfoo.so,它依赖于一个函数read,我想在文件read.c中定义自己。

我编译并将所有内容链接在一起,但在运行时出现错误

/home/bar/src/libfoo.so: undefined symbol: sread.

nm 报告符号已定义

$nm baz | grep sread
  00000000000022f8 t sread

但 ldd 报告符号未定义

$ldd -r baz | grep sread 
undefined symbol: sread (/home/bar/src/libfoo.so)

什么给了? libfoo.so 是一个共享库这一事实有什么问题吗?

【问题讨论】:

  • 也许您应该发布所有共享对象和可执行文件的完整链接行以阐明主题。

标签: linux linker shared-libraries


【解决方案1】:

首先,定义一个名为“read”的函数是个坏主意(TM),因为它是所有 UNIXen 上的标准 libc 函数。执行此操作时程序的行为未定义。

其次,您在libbaz.so 中定义的read 函数在nm 输出中标有't'。这意味着这个函数是本地的(在libbaz.so 之外不可见)。全局函数由nm标记为'T'。

您在 read.c 中定义 'static int read(...)' 时是否使用了它? 如果没有,您在编译和链接libbaz.so 时是否使用了链接器脚本、attribute((visibility(hidden))) 或命令行上的-fvisibility=hidden?

【讨论】:

  • 函数的名称实际上并没有被读取,我只是想让事情变得简单。啊...你是对的,我正在使用 -Wl,--version-script,其中包含一个文件,该文件将所有符号保持在本地,除了我希望导出的两个符号。我显然也需要导出读取函数。
【解决方案2】:

C 代码用 G++ 编译,然后链接时也会出现上述错误。 G++ 执行名称修改,因此实际符号可能类似于“_Zsds_[function_name]_”,导致链接器在搜索未修改名称时阻塞。

我今天遇到了同样的行为,除了我的问题按照Wikipedia 中概述的操作得到解决。基本上,使用 C++ 编译器编译的 C 代码将在符号表中具有“损坏”的名称,从而导致 C 样式的符号解析失败。

【讨论】:

    【解决方案3】:

    当您构建共享库时,您需要从同一库或另一个(共享)库中解析所有个未定义的符号。链接器将不用您的应用程序中的符号解析库中的未定义符号。

    【讨论】:

    • 我应该澄清一下,baz 实际上是一个共享库。那么这是否意味着我应该创建一个只包含读取功能的共享库,并链接到这个?是否有明确的方法告诉链接器使用其他共享库(比如 libread.so)解析共享库 libfoo.so 中的未定义符号?
    • 你大错特错了:运行时加载器会很高兴地用主可执行文件中的符号解析共享库中的未定义符号,前提是该符号在其动态表中“导出”(例如,当可执行文件与 -rdynamic 链接)。
    • @codehippo 你没有说 baz 是一个共享库,这个名字也不会导致这种假设。
    • @Employed 俄语 将可执行文件与导出的符号链接是非常不寻常的,我不认为 OP 正在使用这种罕见的技术,好像他这样做了,他可能不需要问他所做的问题。
    猜你喜欢
    • 2011-03-19
    • 2012-07-16
    • 2011-01-20
    • 2012-07-31
    • 2019-05-31
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多