0

我有错误的共享库(未定义的符号)。

当我第一次调用 dlopen() 时,我得到一个 NULL 结果,并从 dlerror() 得到正确的错误消息。

如果我忽略错误消息并使用相同的参数调用 dlopen(),我第二次得到一个非空句柄(这表明库已成功加载)。这显然是错误的。

这个问题在 Ubuntu 11.04 下出现(IIRC,10.10 没有这个问题)。Centos 5.5 没有出现这个问题。

特别是,这个问题发生在 Tcl 解释器中。它将尝试加载共享库,首先使用规范化的绝对​​路径,如果再次失败,则使用用户提供的确切路径字符串。就我而言,两者都应该失败,但第二次调用在 Ubuntu 11.04 下错误地成功了。

奇怪的是,我只能使用我的确切生产共享库来重现这个问题。如果我制作了一个精简的共享库,它就可以正常工作。

像这样的程序足以显示我的生产库的问题:

#include <stdio.h>
#include <dlfcn.h>

int main()
{
  void* h;

  h = dlopen("./prod.so", RTLD_NOW | RTLD_LOCAL);
  printf("h is %p\n", h);
  printf("err is %s\n", dlerror());
  h = dlopen("./prod.so", RTLD_NOW | RTLD_LOCAL);
  printf("h is %p\n", h);
}
4

1 回答 1

0

一段时间以来,我偶尔会看到这个问题的边缘,但我还没有确定导致它的确切原因(我还没有找到适合 Google 的东西,但这不是 Ubuntu 感觉的东西标题更改,因此很难找到)。有人在传递 IRC 时向我提到出了什么问题,但那是前一阵子,当时我在另一个问题上由我的眼球决定,我没有保存足够的信息(写下来或在内存中)能够重建它。所以这是我最好的回忆……</p>

据我所知,构建某些库时使用的链接选项或解析依赖库时使用的默认选项发生了一些变化,这导致 Tcl 无法加载它所依赖的所有内容。因为它无法加载某些依赖项——甚至可能是一个依赖项的依赖项——它无法加载库的其余部分(因为RTLD_NOW你想要的标志)并且你到达了现在的位置。它可能很容易修复,例如通过更改链接时间选项,但我不知道具体出了什么问题。

简而言之,这是某人的错误,但我不知道是谁。许多(但不是全部!)Linux 发行商并不擅长就他们发现或创造的问题向上游反馈。

注意:如果您上面的代码是 Tcl 命令的代理load,请注意这本身就是一个棘手的领域

于 2011-07-06T13:31:02.620 回答