Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588335
  • 博文数量: 50
  • 博客积分: 4764
  • 博客等级: 上校
  • 技术积分: 597
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-18 09:00
个人简介

资深IT码农,擅长Linux、C/C++、bash

文章分类

全部博文(50)

文章存档

2015年(17)

2014年(2)

2011年(7)

2010年(4)

2009年(20)

分类: C/C++

2015-07-23 16:48:41

如何在编译动态链接库时报告未定义符号的错误

冷胜魁(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):
  • --no-undefined, -z defs
例如:
$ 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
阅读(8220) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~