【问题标题】:Interesting GCC Linking有趣的 GCC 链接
【发布时间】:2015-05-28 16:52:59
【问题描述】:

我最近在玩符号和函数指针,发现虽然以下代码运行良好:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    printf("%p\n",printf); // <--this line makes it work
    int (*printfptr)(const char * restrict, ...);
    printfptr = 0x1001fe910;
    (*printfptr)("Hello world\n");
    return 0;
}

这不是:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    // printf("%p\n",printf); // <-- commenting this out breaks it
    int (*printfptr)(const char * restrict, ...);
    printfptr = 0x1001fe910;
    (*printfptr)("Hello world\n");
    return 0;
}

(EXC_BAD_ACCESS)

当代码中没有对printf 的引用时,为什么取消引用完全相同的指针会导致问题?即使这样也可以正常工作:

#include <stdio.h>    
int main(int argc, const char * argv[]) {
    int (*printfptr)(const char * restrict, ...);
    printfptr = 0x1001fe910;
    (*printfptr)("Hello world\n");
    return 0;
}
void *_ = printf; // <-- because of this

这是为什么?

【问题讨论】:

  • 在第二种情况下,链接器不知道它应该链接到“printf”函数,所以它的实现不存在。在第一种情况下,代码使用printf,所以它是链接的。
  • 如果你调用未定义的行为,你会得到未定义的结果。指针文字值根本不能保证工作。主要问题是,如果代码中没有符号名称printf,系统就无法知道它需要使printf 可用于您的代码。

标签: c pointers gcc linker dynamic-linking


【解决方案1】:

在共享对象 (.so) 上,符号仅在首次使用时才真正解析。默认情况下,链接器设置选项-z lazy 告诉:

       When generating an executable or shared  library,  mark  it  to
       tell  the  dynamic  linker to defer function call resolution to
       the point when the function is called  (lazy  binding),  rather
       than at load time.  Lazy binding is the default.

您可以通过提供选项 -z now 来更改该行为。

man ld 了解所有血腥细节。

编辑:解析符号是通过 POSIX 系统上的动态链接 API 完成的。在&lt;dlfcn.h&gt; 中定义的函数dlsym()dlopen()dlclose()dlerror()。此版本已添加,以便您可以搜索这些名称。

【讨论】:

  • 一方面我想投票,因为它回答了 OP 的为什么问题并解释了如何调整链接器。另一方面,我想投反对票,因为它鼓励了那种糟糕的编码。
  • 问题是,有时您需要深入研究这类东西。我现在有两个项目,我不得不求助于这个 API(一个遗留的嵌入式系统仿真和一种简化的内部网络服务器,它允许插件可以在不停止的情况下动态加载)。我通常避免系统特定的东西,但如果你必须实现一些特定的功能,那就没有办法了。所以我更愿意至少给出寻找的方向,即使它不符合标准且不便携。
  • comp.lang.c 中限制只回答超便携的东西是可以的,所以,我认为我们还应该提供有关实际实现的信息。
猜你喜欢
  • 2018-08-07
  • 2018-08-20
  • 2014-11-26
  • 2012-03-21
  • 2011-08-06
  • 2023-03-30
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
相关资源
最近更新 更多