如何在编译动态链接库时报告未定义符号的错误
冷胜魁(Seaquester)
lengshengkui@outlook.com
2014-10-22
默认情况下,gcc在编译动态链接库(.so,shared object,共享库),不会报告未定义符号(undefined symbol)错误,只有在运行才会发现这类错误。
通过nm可以查看有哪些符号没有定义:
nm -u libxxx.so | grep U
或者
nm libxxx.so | grep U
这些符号包括定义在其他动态链接库中的,这些符号通常不是问题,只要我们的动态链接库有链接这些动态链接库,并且这些动态链接库都存在。
看下面的例子:
$ nm -u libsilly.so | grep U
U fclose@@GLIBC_2.2.5
U fopen@@GLIBC_2.2.5
U forgot_to_define
$ ldd libsilly.so
linux-vdso.so.1 => (0x00007fffb5bff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f26c1178000)
/lib64/ld-linux-x86-64.so.2 (0x0000003526000000)
未定义的符号有三个,其中fclose和fopen都属于glibc,而且,libsilly.so链接了glibc,所以,这些符号不是问题。
有问题的是最后一个符号forgot_to_define。它不是第三方库提供的,但是没有定义!当libsilly.so被加载的时候,会导致错误。
gcc的文档说,在编译动态链接库时找不到符号(不在任何外部共享库文件里面,自己的程序也没有定义)也允许编译通过是有原因的,参见 ld 的manual中 --allow-shlib-undefined 的解释。就是允许用户链接时用一个版本的共享库,运行时加载用的另外一个版本的共享库,只要加载时的共享库里面有这个符号就行。所以就先让你找不到符号也编译通过了。如果是编译可执行程序,这种链接时找不到定义的符号就直接报错了。其实这种特性应该是比较少用,最好在共享库链接时碰到这个未找到的符号也报错。
我们可以通过linker的参数来强制gcc报告这种错误(具体细节请看ld的manual):
例如:
$ cc -shared -fPIC -Wall -O -o libsilly.so silly.c -Wl,-z,defs
/tmp/cczDTtMp.o: In function `doit':
silly.c:(.text+0x19): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
阅读(8378) | 评论(0) | 转发(0) |