生成可执行的输出文件时,如果有任何未定义符号,则链接编辑器的缺省行为是终止并生成相应的错误消息。如果可重定位目标文件中的符号引用从未与符号定义匹配,则表示此符号未定义:
$ cat main.c extern int foo(); main() { return (foo()); } $ cc -o prog main.c Undefined first referenced symbol in file foo main.o ld: fatal: Symbol referencing errors. No output written to prog |
同样,如果使用共享库创建动态可执行文件,并且该库中的符号引用始终未解析,则会产生未定义符号错误。
$ cat foo.c extern int bar; foo() { return (bar); } $ cc -o libfoo.so -G -K pic foo.c $ cc -o prog main.c -L. -lfoo Undefined first referenced symbol in file bar ./libfoo.so ld: fatal: Symbol referencing errors. No output written to prog |
要允许未定义符号(与上一个示例一样),可使用链接编辑器的 -z nodefs 选项抑制出现缺省错误状态。
使用 -z nodefs 选项时应谨慎。如果在执行进程期间需要不可用的符号引用,则会发生致命的运行时重定位错误。在初始执行和测试应用程序期间可能会检测到此错误。然而,执行路径越复杂,检测此错误状态需要的时间就越长,这将非常耗时且开销很大。
将可重定位目标文件中的符号引用绑定到隐式定义的共享库中的符号定义时,符号也可以保持未定义。例如,继续使用上一个示例中使用的文件 main.c 和 foo.c:
$ cat bar.c int bar = 1; $ cc -o libbar.so -R. -G -K pic bar.c -L. -lfoo $ ldd libbar.so libfoo.so => ./libfoo.so $ cc -o prog main.c -L. -lbar Undefined first referenced symbol in file foo main.o (symbol belongs to implicit \ dependency ./libfoo.so) ld: fatal: Symbol referencing errors. No output written to prog |
prog 是使用对 libbar.so 的显式引用生成的。libbar.so 依赖于 libfoo.so。因此,将从 prog 建立对 libfoo.so 的隐式引用。
因为 main.c 对 libfoo.so 提供的接口进行特定引用,所以 prog 依赖于 libfoo.so。但是,在要生成的输出文件中将仅记录显式共享库的依赖项。因此,如果开发一种不再依赖于 libfoo.so 的新版本 libbar.so,则 prog 将无法运行。
因此,此类型的绑定被认为是致命错误。必须通过在链接编辑 prog 期间直接引用库来使隐式引用变为显式引用。前面示例中显示的致命错误消息中会提示需要的引用。