无论要生成哪种类型的输出文件,未解析的弱符号引用不会产生致命错误状态。
如果要生成静态可执行文件,则可将此符号转换为绝对符号,并指定值零。
如果要生成动态可执行文件或共享库,则可将此符号保留为未定义弱引用,并指定值零。在进程执行期间,运行时链接程序将搜索此符号。如果运行时链接程序未找到匹配项,则将此引用绑定到地址零,而不是生成致命重定位错误。
以前,这些未定义弱引用符号被用作一种机制,用于测试功能是否存在。例如,在共享库 libfoo.so.1 中可能使用了以下 C 代码段:
#pragma weak foo extern void foo(char *); void bar(char * path) { void (* fptr)(char *); if ((fptr = foo) != 0) (* fptr)(path); } |
生成引用 libfoo.so.1 的应用程序时,无论是否找到符号 foo 的定义,链接编辑都将成功完成。如果在执行此应用程序时函数地址测试为非零,则将调用此函数。但是,如果未找到符号定义,则函数地址测试将为零,因此不调用此函数。
编译系统将此地址比较方法视为未定义语义,这将导致在优化时删除测试语句。此外,运行时符号绑定机制会对使用此方法设定其他限制。这些限制防止所有动态库使用一致的模型。
建议不要按照此方式使用未定义弱引用。相反,应将 dlsym(3C) 与 RTLD_DEFAULT 或 RTLD_PROBE 句柄配合使用,以测试符号是否存在。 请参见测试功能。