当目标文件和静态库中同时存在相同符号时,链接器不会发出多个定义错误 [英] Linker does not emit multiple definition error when same symbol coexists in object file and static library
问题描述
给出一个在静态库中具有签名void some_func()
的已编译函数,而在目标文件中另一个具有相同void some_func()
签名的函数希望将它们链接在一起时会出现多个定义"错误.
Given a compiled function with signature void some_func()
in a static library, and another one with the same void some_func()
signature in a object file one expects that when you link them together a "multiple definition" error should have occured.
但事实并非如此.据我观察,链接器(已通过GCC和MSVC工具链进行了测试)选择了驻留在目标文件中的实现,而不会发出任何错误或警告.
But this is not the case. As far as i've observed the linkers (tested with GCC and MSVC toolchains) choose the implementation residing in the object file without emitting any error or warning.
给出以下POC:
somelib.h
somelib.h
#ifndef _SOMELIB_H_
#define _SOMELIB_H_
void some_func();
#endif /* _SOMELIB_H_ */
somelib.c
somelib.c
#include "somelib.h"
#include <stdio.h>
void some_func()
{
printf("some_func in library\n");
}
troublingheader.h
troublingheader.h
#ifndef _TROUBLING_HEADER_H_
#define _TROUBLING_HEADER_H_
void some_func();
#endif /* _TROUBLING_HEADER_H_ */
troublingsource.c
troublingsource.c
#include "troublingheader.h"
#include <stdio.h>
void some_func()
{
printf("Troubling func\n");
}
main.c
#include <stdio.h>
#include "somelib.h"
int main()
{
some_func();
}
还有一个简单的Makefile来帮助构建(首先创建tmp文件夹):
And a simple Makefile to assist building (create tmp folder first):
tmp/wat.exe: tmp/libsomelib.a tmp/main.c.o tmp/troublingsource.c.o
gcc -static -static-libgcc -Ltmp -otmp/wat.exe tmp/main.c.o tmp/troublingsource.c.o -lsomelib
tmp/main.c.o:
gcc -Wall -Wextra -c -g -O0 src/main.c -o tmp/main.c.o
tmp/troublingsource.c.o:
gcc -Wall -Wextra -c -g -O0 src/troublingsource.c -o tmp/troublingsource.c.o
tmp/somelib.o:
gcc -Wall -Wextra -c -g -O0 src/somelib.c -o tmp/somelib.c.o
tmp/libsomelib.a: tmp/somelib.o
ar rcs tmp/libsomelib.a tmp/somelib.c.o
运行最终可执行文件时,内容"Troubling func"如上所示.
When running the final executable, the contents "Troubling func" are shown as above described.
有人可以向我解释为什么会这样吗?
Can someone explain me why this happens?
推荐答案
In the case of the GNU linker ld
,
invoked by GCC, what you have observed is explained by the following points.
-
链接序列中的目标文件被无条件地添加到链接中, 是否包含程序需要的符号.
An object file in the linkage sequence is added to the linkage unconditionally, whether it contains symbols that the program needs or not.
静态库是目标文件和目录"的档案 链接器可以检查的.
A static library is an archive of object files together with a "table of contents" that the linker can inspect.
默认情况下,不在链接序列中添加静态库中的目标文件 无条件地链接.链接器仅在静态库中搜索 查找已观察到要引用的符号的定义, 但尚未定义,通过已将对象文件 添加到链接中.提取目标文件 仅从库中添加并添加到链接中,前提是它提供了此类符号的定义.仅当链接器添加时 已经需要它提供的一些定义.
By default, an object file within a static library in the linkage sequence is not added to the linkage unconditionally. The linker searches a static library only to find definitions of symbols that it has observed to be referenced, but not defined, by object files already added to the linkage. An object file is extracted from the library and added to the linkage only if it provides definitions of such symbols. It is added only if the linker already needs some of the definitions that it provides.
为避免混淆,我们将更改输出消息:
For the avoidance of confusion, we'll change the output message:
"some_func in library\n"
收件人:
"some_func in somelib.o"
然后对这些要点进行演示,以解释您所看到的内容:
Then a demonstration of these points that explains what you've seen:
案例1
从静态库链接troublingsource.o
本身和somelib.o
.
链接顺序:main.o
,troublingsource.o
,libsomelib.a
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o main.o main.c
ar rcs libsomelib.a somelib.o
gcc -o test main.o troublingsource.o -L. -lsomelib
./test
Troubling func
这里:
-
main.o
被无条件添加到链接中.
发现在 - 符号
main
找到 - 符号
some_func
,但未在main.o
中定义
-
troublingsource.o
被无条件添加到链接中
在 - 先前引用过但未定义的符号
some_func
. - 没有未解决的参考文献.甚至没有搜索到
libsomelib.a
.
main.o
中定义了troublingsource.o
中发现了main.o
was added unconditionally to the linkage.- Symbol
main
was found defined inmain.o
- Symbol
some_func
was found referenced but not defined inmain.o
troublingsource.o
was added unconditionally to the linkage- Symbol
some_func
, previously referenced but not defined, was found defined introublingsource.o
. - No unresolved references remained.
libsomelib.a
was not even searched.
案例2
从静态库链接someblib.o
本身和troublingsource.o
.
链接顺序:main.o
,somelib.o
,libtroublingsource.a
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o main.o main.c
ar rcs libtroublingsource.a troublingsource.o
gcc -o test main.o somelib.o -L. -ltroublingsource
./test
some_func in somelib.o
这里:
-
main.o
被无条件添加到链接中.
发现在 - 符号
main
找到 - 符号
some_func
,但未在main.o
中定义
-
someblib.o
被无条件添加到链接中
在 - 以前引用过但未定义的符号
some_func
. - 没有未解决的参考文献.甚至没有搜索到
libtroublingsource.a
.
main.o
中定义了somelib.o
中找到了main.o
was added unconditionally to the linkage.- Symbol
main
was found defined inmain.o
- Symbol
some_func
was found referenced but not defined inmain.o
someblib.o
was added unconditionally to the linkage- Symbol
some_func
, previously referenced but not defined, was found defined insomelib.o
. - No unresolved references remained.
libtroublingsource.a
was not even searched.
案例3
从单独的静态库链接someblib.o
和troublingsource.o
.
Link someblib.o
and troublingsource.o
from separate static libraries.
链接顺序:main.o
,libsomelib.a
,libtroublingsource.a
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o main.o main.c
ar rcs libsomelib.a somelib.o
ar rcs libtroublingsource.a troublingsource.o
gcc -o test main.o -L. -lsomelib -ltroublingsource
./test
some_func in somelib.o
这里:
-
main.o
被无条件添加到链接中.
发现在 - 符号
main
找到 - 符号
some_func
,但未在main.o
中定义
在 -
libsomeblib.a
中搜索了提供some_func
定义的目标文件.
- 在
libsomelib.a
的成员somelib.o
中找到some_func
的定义
从 -
somelib.o
并将其添加到链接中. - 没有未解决的参考文献.甚至没有搜索到
libtroublingsource.a
.
main.o
中定义了libsomelib.a
中提取main.o
was added unconditionally to the linkage.- Symbol
main
was found defined inmain.o
- Symbol
some_func
was found referenced but not defined inmain.o
libsomeblib.a
was searched for an object file providing a definition ofsome_func
- A definition of
some_func
was found in membersomelib.o
oflibsomelib.a
somelib.o
was extracted fromlibsomelib.a
and added to the linkage.- No unresolved references remained.
libtroublingsource.a
was not even searched.
案例4
链接someblib.o
本身和troublingsource.o
本身.
链接顺序:main.o
,somelib.o
,troublingsource.o
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o troublingsource.o troublingsource.c
gcc -I. -c -o main.o main.c
gcc -o test main.o somelib.o troublingsource.o
troublingsource.o: In function `some_func':
troublingsource.c:(.text+0x0): multiple definition of `some_func'
somelib.o:somelib.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
这里:
-
main.o
被无条件添加到链接中.
发现在 - 符号
main
找到 - 符号
some_func
,但未在main.o
中定义
-
someblib.o
被无条件添加到链接中
发现在 - 符号
some_func
先前已引用但未定义. -
troublingsource.o
被无条件添加到链接中
在 - 符号
some_func
已全部定义在somelib.o
中. 错误.
main.o
中定义了somelib.o
中定义的troublingbsource.o
中再次定义的main.o
was added unconditionally to the linkage.- Symbol
main
was found defined inmain.o
- Symbol
some_func
was found referenced but not defined inmain.o
someblib.o
was added unconditionally to the linkage- Symbol
some_func
, previously referenced but not defined, was found defined insomelib.o
troublingsource.o
was added unconditionally to the linkage- Symbol
some_func
, allready defined insomelib.o
, was found defined again introublingbsource.o
. Error.
案例5
从静态库链接someblib.o
.
链接顺序:libsomelib.a
main.o
gcc -I. -c -o somelib.o somelib.c
gcc -I. -c -o main.o main.c
ar rcs libsomelib.a somelib.o
gcc -o test -L. -lsomelib main.o
main.o: In function `main':
main.c:(.text+0xa): undefined reference to `some_func'
collect2: error: ld returned 1 exit status
这里:
-
在将任何目标文件添加到
-
libsomelib.a
之前,遇到了 -
libsomelib.a
连锁.那时没有引用任何符号,但未定义任何符号,因此libsomelib.a
甚至没有被搜索到, -
main.o
被无条件添加到链接中.
发现在 - 符号
main
找到 - 符号
some_func
,但未在main.o
中定义
- 没有其他要链接的目标文件或库.
some_func
最终是一个未定义的引用. 错误.
main.o
中定义了libsomelib.a
was encountered before any object files were added to the linkage. At that point no symbols were referenced but undefined, solibsomelib.a
was not even searched,main.o
was added unconditionally to the linkage.- Symbol
main
was found defined inmain.o
- Symbol
some_func
was found referenced but not defined inmain.o
- There were no further object files or libraries to link.
some_func
was finally an undefined reference. Error.
这篇关于当目标文件和静态库中同时存在相同符号时,链接器不会发出多个定义错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!