【问题标题】:Handling symbol lookup errors at runtime using C使用 C 在运行时处理符号查找错误
【发布时间】:2014-06-12 20:12:51
【问题描述】:

假设我有一个导出三个函数的动态库:

void lib_function(void);
void lib_extra_function(void);
int  lib_runtime_version(int v);

并且lib_extra_function 已添加到库的第 2 版中。

如果使用 lib_extra_function 的应用程序是在安装了库版本 2 的系统上构建的,然后在仅提供版本 1 的系统上运行,则在调用 lib_extra_function 时会引发“symbol lookup error: ./main: undefined symbol: lib_extra_function”动态链接器错误.

但是,如果应用程序尝试使用库提供的版本信息并有条件地调用lib_extra_function,则不会引发错误,即使lib_extra_function 仍未定义。

voif f()
{
    if(lib_runtime_version() >= 2) {
        lib_extra_function();
    } else {
        // try some workaround
    }
}

现在,这种行为是由任何标准规定的吗?如果不是,它是否特定于 Linux?其他系统(OSX、BSD)中的链接器表现如何?

【问题讨论】:

  • “如果使用lib_extra_function 的应用程序是针对版本 2 编译的,并且在仅提供版本 1 的系统上运行......” - 我不明白,一切都已编译和链接,但是当你运行你的程序时,动态链接器会给你错误?还是构建过程中发生链接错误?
  • @Dabo 我的意思是应用程序使用较新版本的库构建但使用旧版本运行的情况。运行时引发链接器错误。我稍微澄清了我的问题。
  • 如果它已经用版本 2 编译,如果没有链接,它如何在版本 1 的系统中引发错误?我认为任何操作系统上的任何加载程序都不会检查代码以查看是否所有功能都已实际定义..
  • 我假设使用动态库。在这种情况下,加载程序(在 Linux 的情况下为ld-linux.so)负责解析符号。
  • @el.pescado 如果您在构建阶段链接到新库,一切都找到并且一切正常,稍后在运行时动态链接器会寻找适当的共享库(您在此处描述的错误是共享库的经典错误,所以我假设是这种情况)并且它创建了另一个版本,即 previos 版本,加载它并且您的代码崩溃并烧录为所需的功能(符号)不存在。

标签: c linux linker undefined-reference


【解决方案1】:

现在,这种行为是由任何标准规定的吗?

没有。

如果不是,它是 Linux 特有的吗?

没有。 lazy 运行时符号解析的系统支持这种行为。

一般来说你应该避免这样做:

if(lib_runtime_version() >= 2) {
    lib_extra_function();

有几个原因:

  • 它根本不适用于执行急切符号解析的系统,
  • 如果最终用户设置LD_BIND_NOW(这是上面的特殊情况),它将爆炸,并且
  • 它违反了DRY principle

相反,如果一个函数是可选的,使用dlsym 来确定它是否可用:

p_extra = dlsym(..., "lib_extra_function");
if (p_extra != NULL) {
    ....

【讨论】:

  • 问题是,期望用户设置LD_BIND_ALL 是否合理?
  • @el.pescado 用户在尝试调试某些东西时经常设置 LD_BIND_NOW,所以是的,期望设置它是合理的。一些用户还设置了 LD_BIND_NOW 以避免“在运行时意外未解析的符号”(即,如果他们犯了错误并忘记定义一些必需的符号,他们希望它在开始时可预见地失败)。
猜你喜欢
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-25
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多