【问题标题】:Cannot load any more object with static TLS无法使用静态 TLS 加载更多对象
【发布时间】:2013-01-31 06:35:23
【问题描述】:

我有一个使用dlopen() 加载附加模块的应用程序。应用程序和模块使用 gcc 4.6 构建在 Ubuntu 12.04 x86_64 上,但用于 i386 架构。然后将二进制文件复制到另一台具有完全相同操作系统的机器上并正常工作。

但是,如果将它们复制到 Ubuntu 12.04 i386,则某些(但不是全部)模块将无法加载并显示以下消息:

dlopen: cannot load any more object with static TLS

我怀疑这是由__thread 变量的使用引起的。但是,这些变量不会在加载的模块中使用 - 仅在加载模块本身中使用。

有人可以提供任何其他信息吗,可能是什么原因?

我正在减少 __thread 变量的数量并优化它们(使用 -ftls-model 等),我只是好奇为什么它在几乎相同的系统上不起作用。

【问题讨论】:

标签: c++ linux gcc ubuntu dlopen


【解决方案1】:

我怀疑这是由于使用了 __thread 变量造成的。

正确。

但是,这些变量不会在加载的模块中使用 - 仅在加载模块本身中使用。

不正确。您自己可能没有使用__thread,但是您静态链接到模块中的某些库正在使用它们。您可以通过以下方式确认:

readelf -l /path/to/foo.so | grep TLS

可能是什么原因?

模块正在使用-ftls-model=initial-exec,但应该使用-ftls-model=global-dynamic。这种情况最常发生在(部分)链接到foo.so 的代码是在没有-fPIC 的情况下构建的。

将非-fPIC 代码链接到共享库在x86_64 上是不可能的,但在ix86 上是允许的(并且会导致许多微妙的问题,比如这个)。

更新:

我有 1 个模块在没有 -fPIC 的情况下编译,但我根本没有设置 tls-model,据我记得默认值不是 initial-exec

  • 每个 ELF 映像(可执行文件或共享库)只能有一个 tls 模型。
  • 对于非-fPIC 代码,TLS 模型默认为initial-exec

因此,如果您将一个使用__thread 的非-fPIC 对象链接到foo.so,那么foo.so所有 TLS 将获得initial-exec

那么为什么会出现问题——因为如果使用了initial-exec,那么tls变量的数量是有限的(因为它们不是动态分配的)?

正确。

【讨论】:

  • 我不太明白。我有1个没有-fPIC编译的模块(我正在试验性能),但我根本没有设置tls-model,据我记得默认值不是initial-exec?那么为什么它会导致问题 - 因为如果使用 initial-exec 则 tls 变量的数量是有限的(因为它们不是动态分配的)?我已经通过减少 __thread 变量的数量解决了我的问题(它们在几个模块中使用的 .h 标头中,我把所有的都放在一个中)并且错误消失了,但我仍然很好奇。
猜你喜欢
  • 2017-03-09
  • 1970-01-01
  • 2013-10-16
  • 1970-01-01
  • 2021-02-15
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 2023-02-15
相关资源
最近更新 更多