有趣的 GCC 链接
Interesting GCC Linking
我最近在研究符号和函数指针,发现尽管以下代码运行良好:
#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
这是为什么?
在共享对象 (.so) 上,符号仅在首次使用时才真正解析。默认情况下,linker 设置选项 -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 系统上使用动态 link API 解析符号。在 <dlfcn.h>
中定义的函数 dlsym()
、dlopen()
、dlclose()
和 dlerror()
。此版本添加,以便您可以搜索这些名称。
我最近在研究符号和函数指针,发现尽管以下代码运行良好:
#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
这是为什么?
在共享对象 (.so) 上,符号仅在首次使用时才真正解析。默认情况下,linker 设置选项 -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 系统上使用动态 link API 解析符号。在 <dlfcn.h>
中定义的函数 dlsym()
、dlopen()
、dlclose()
和 dlerror()
。此版本添加,以便您可以搜索这些名称。