Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1713673
  • 博文数量: 143
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1462
  • 用 户 组: 普通用户
  • 注册时间: 2016-08-23 11:14
文章分类

全部博文(143)

文章存档

2022年(3)

2021年(13)

2020年(21)

2019年(8)

2018年(28)

2017年(7)

2016年(63)

我的朋友

分类: LINUX

2020-09-07 03:04:58

符号表中的"U" The symbol is undefined.
表示在目标文件中被调用,但并没有在目标中定义。 表明需要其它目标文件(如:.o .a .so)的支持。

一. 在常规目标文件中“U”
首先编译阶段会报warning, 其次如果该符号不在任何外部目标文件里面, 链接阶段会报error, 执行(加载,运行)会段错误。
1. 编译阶段会报warning: 需要加编译选项“-Wall”才会显示“warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]”
2. 链接阶段会报error: gcc默认的编译选项会链接不过“(.text+0x20): undefined reference to `funcB'” “collect2: error: ld returned 1 exit status”, 需要加编译选项“-Xlinker --unresolved-symbols=ignore-all” 就可以使链接通过。
  但是,如果要创建目标文件是共享库(.so), 此时默认不会报error。 需要加“-Xlinker --no-undefined”才会报error。 [在“man ld”中未找到对此(要创建目标文件是共享库时,默认不报error)的解释。不要被如下灰色段落误解,灰色段落针对的是被链接的共享库,而非此处正在创建的共享库]
3. 执行会段错误: “Segmentation fault”。

正常情况(外部目标文件中有funcB符号)

点击(此处)折叠或打开

  1. gcc -c func_parameters_funcB.c
  2. ar -cr libfuncB.a func_parameters_funcB.o
  3. gcc func_parameters.c libfuncB.a 或 gcc -Wall func_parameters.c libfuncB.a
点击(此处)折叠或打开
  1. gcc -fPIC -c func_parameters_funcB.c
  2. gcc -shared func_parameters_funcB.o -o libfuncB.so
  3. gcc func_parameters.c libfuncB.so 或 gcc -Wall func_parameters.c libfuncB.so

相反,如果我们不给它链接任何外部目标文件(外部目标文件中无funcB符号)

点击(此处)折叠或打开

  1. gcc func_parameters.c
  2. /tmp/ccJlpwCP.o: In function `main':
  3. func_parameters.c:(.text+0x20): undefined reference to `funcB'
  4. collect2: error: ld returned 1 exit status
分解来看:

点击(此处)折叠或打开

  1. gcc -c func_parameters.c
  2. gcc -Wall -c func_parameters.c
  3. func_parameters.c: In function 'main':
  4. func_parameters.c:14:5: warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]
  5.      funcB();
  6.      ^

点击(此处)折叠或打开

  1. gcc func_parameters.o
  2. func_parameters.o: In function `main':
  3. func_parameters.c:(.text+0x20): undefined reference to `funcB'
  4. collect2: error: ld returned 1 exit status

点击(此处)折叠或打开

  1. gcc -Xlinker --unresolved-symbols=ignore-all func_parameters.o

同样的,
点击(此处)折叠或打开
  1. gcc -shared -fPIC func_parameters.c -o libfunc.so
分解来看:

点击(此处)折叠或打开

  1. gcc -fPIC -c func_parameters.c
  2. gcc -Wall -fPIC -c func_parameters.c
  3. func_parameters.c: In function 'main':
  4. func_parameters.c:14:5: warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]
  5.      funcB();
  6.      ^

点击(此处)折叠或打开

  1. gcc -shared func_parameters.o -o libfunc.so

点击(此处)折叠或打开

  1. gcc -shared -Xlinker --no-undefined func_parameters.o -o libfunc.so
  2. func_parameters.o: In function `main':
  3. func_parameters.c:(.text+0x20): undefined reference to `funcB'
  4. collect2: error: ld returned 1 exit status

点击(此处)折叠或打开

  1. gcc -shared -Xlinker --no-undefined -Xlinker --unresolved-symbols=ignore-all func_parameters.o -o libfunc.so

二.在被链接的共享库中“U”
共享库(“U”),被用来创建可执行的目标文件时
点击(此处)折叠或打开
  1. gcc -Wall -shared -fPIC func_parameters_funcB_invoke_funcC.c -o libfuncC.so
  2. func_parameters_funcB_invoke_funcC.c: In function 'funcB':
  3. func_parameters_funcB_invoke_funcC.c:5:5: warning: implicit declaration of function 'funcC' [-Wimplicit-function-declaration]
  4.      funcC();
  5.      ^

点击(此处)折叠或打开

  1. gcc -Wall func_parameters.c libfuncC.so
  2. func_parameters.c: In function 'main':
  3. func_parameters.c:14:5: warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]
  4.      funcB();
  5.      ^
  6. libfuncC.so: undefined reference to `funcC'
  7. collect2: error: ld returned 1 exit status

点击(此处)折叠或打开

  1. gcc -Wall -Xlinker --unresolved-symbols=ignore-all func_parameters.c libfuncC.so
  2. func_parameters.c: In function 'main':
  3. func_parameters.c:14:5: warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]
  4.      funcB();
  5.      ^
或者也可以被它控制
点击(此处)折叠或打开
  1. gcc -Wall -Xlinker --allow-shlib-undefined func_parameters.c libfuncC.so
  2. func_parameters.c: In function 'main':
  3. func_parameters.c:14:5: warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]
  4.      funcB();
  5.      ^

共享库(“U”),被用来创建共享库.so(特殊的目标文件)时
点击(此处)折叠或打开
  1. gcc -Wall -shared -fPIC func_parameters_funcB_invoke_funcC.c -o libfuncC.so
  2. func_parameters_funcB_invoke_funcC.c: In function 'funcB':
  3. func_parameters_funcB_invoke_funcC.c:5:5: warning: implicit declaration of function 'funcC' [-Wimplicit-function-declaration]
  4.      funcC();
  5.      ^

点击(此处)折叠或打开

  1. gcc -Wall -shared -fPIC func_parameters.c -o libfunc.so libfuncC.so
  2. func_parameters.c: In function 'main':
  3. func_parameters.c:14:5: warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]
  4.      funcB();
  5.      ^
[此时,如灰色段落所说,默认不会报error。]

man ld: “注:个人理解, 本文中的常规目标文件特指创建目标文件时‘用的中间文件(.o .a ...)’, 区别于‘用的共享库(.so)’”
点击(此处)折叠或打开
  1.        --no-undefined
  2.        -z defs
  3.            Report unresolved symbol references from regular object files. This is done even if the linker is creating a non-symbolic shared
  4.            library. The switch --[no-]allow-shlib-undefined controls the behaviour for reporting unresolved references found in shared
  5.            libraries being linked in.

点击(此处)折叠或打开

  1.        --allow-shlib-undefined
  2.        --no-allow-shlib-undefined
  3.            Allows or disallows undefined symbols in shared libraries. This switch is similar to --no-undefined except that it determines
  4.            the behaviour when the undefined symbols are in a shared library rather than a regular object file. It does not affect how
  5.            undefined symbols in regular object files are handled.

  6.            The default behaviour is to report errors for any undefined symbols referenced in shared libraries if the linker is being used to
  7.            create an executable, but to allow them if the linker is being used to create a shared library.

  8.            The reasons for allowing undefined symbol references in shared libraries specified at link time are that:

  9.            · A shared library specified at link time may not be the same as the one that is available at load time, so the symbol might
  10.                actually be resolvable at load time.

  11.            · There are some operating systems, eg BeOS and HPPA, where undefined symbols in shared libraries are normal.

  12.                The BeOS kernel for example patches shared libraries at load time to select whichever function is most appropriate for the
  13.                current architecture. This is used, for example, to dynamically select an appropriate memset function.

点击(此处)折叠或打开

  1. --unresolved-symbols=method
  2.            Determine how to handle unresolved symbols. There are four possible values for method:

  3.            ignore-all
  4.                Do not report any unresolved symbols.

  5.            report-all
  6.                Report all unresolved symbols. This is the default.

  7.            ignore-in-object-files
  8.                Report unresolved symbols that are contained in shared libraries, but ignore them if they come from regular object files.

  9.            ignore-in-shared-libs
  10.                Report unresolved symbols that come from regular object files, but ignore them if they come from shared libraries. This can
  11.                be useful when creating a dynamic binary and it is known that all the shared libraries that it should be referencing are
  12.                included on the linker's command line.

  13.            The behaviour for shared libraries on their own can also be controlled by the --[no-]allow-shlib-undefined option.

  14.            Normally the linker will generate an error message for each reported unresolved symbol but the option --warn-unresolved-symbols
  15.            can change this to a warning.

一二参考: linux 编译动态链接库 so,避免运行时才发现函数未

三.函数隐式声明“[-Wimplicit-function-declaration]”
现在,我们回头来看以上举例中都出现过的“warning: 隐式声明函数 'xxx' [-Wimplicit-function-declaration]”, 显然都发生在编译阶段。
出现此类警告的原因: 没有声明原始函数。
一般的解决方式:在程序前面增加函数头说明即可,否则是用默认说明(隐式说明)来解释函数调用规则,比如返回值默认是int就是在你不说明时起作用的。
如下文章写的非常好,不再赘述:
万恶之源:C语言中的隐式函数声明    +    C语言隐式函数声明带来的错误实例(当隐式声明遇到printf)
需要指出的是,通过我在“一”中“正常情况中的.a”的实验, 发现: 当默认使用了隐式声明后, 在链接时并不会对函数参数做检查, 这体现在即使所调用的函数的参数和所定义的函数的参数完全不一致, 所定义的函数仍然会被链接进去(可通过查看创建的目标文件中关键字符串来确定), 但毫无疑问运行时会段错误。 但是,当你声明后,如果二者参数不一致,编译阶段就会报error: too few arguments to function

四.总结,(个人理解: 编译阶段叫“未定义”, 连接阶段叫“未解析”)
在编译阶段, 如果目标文件源文件中有未定义函数, 就会报warning: “warning: implicit declaration of function 'funcB' [-Wimplicit-function-declaration]”
在链接阶段, 如果要创建的目标文件(可以是共享库.so(特殊的目标文件))所要用的常规目标文件中有未解析函数,要被--no-undefined控制(而且, 通过实验发现, 如果要创建的目标文件是共享库.so时,--no-undefined默认是关闭的)。
                                                                           可以被-Xlinker --unresolved-symbols=ignore-in-object-files打开。
         如果被链接的共享库.so中有未解析函数,要被--no-allow-shlib-undefined/--allow-shlib-undefined控制(而且, 如果被链接用于去创建可执行目标文件时, --no-allow-shlib-undefined默认没关闭; 而如果被链接用于去创建共享库.so时, --no-allow-shlib-undefined默认是关闭的)。
                                    也可以被-Xlinker --unresolved-symbols=ignore-in-shared-libs/report-all控制。
         显然综上述两点,这两者还可以同时被-Xlinker --unresolved-symbols=ignore-all/report-all控制。

所以如果我们要检查自己写的.c中是否在链接阶段有未解析函数, 加上-no-undefined 或者 --unresolved-symbols=ignore-in-shared-libs 就可以了
另外如果我们仅仅想测试一个模块,编进去与不编进去,实际占用文件或者段大小,我们可以通过在系统flag中增加-Xlinker --unresolved-symbols=ignore-all, 然后注释掉模块的编译,就可以达到

阅读(4490) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~