在某些情况下,链接器允许多个模块定义具有相同名称的全局符号? [英] in some cases the linker allows multiple modules to define global symbols with the same name?

查看:221
本文介绍了在某些情况下,链接器允许多个模块定义具有相同名称的全局符号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在读一本教科书,上面写着:

I'm reading a textbook which says:

我们看到了编译器如何使用看似随意的约定将符号分配给COMMON和.bss。实际上,此约定是由于在某些情况下链接程序允许多个模块使用相同的名称定义全局符号。

只能定义一次变量?在某些情况下,链接程序允许您多次定义变量?

But isn't that you can only define a variable once? in which cases linker allow you to define a variable more than once?

推荐答案

这始终存在,因此包括以下排列的实际构建:

This comes around all the time, so here is an actual build which covers the permutations of this:

#- Makefile -----
all: 1 2 3 12 13 23
    -./1
    -./2
    -./3
    -./12
    -./13
    -./23
1: main.o 1.o; $(CC) main.o 1.o -o $@
2: main.o 2.o; $(CC) main.o 2.o -o $@
3: main.o 3.o; $(CC) main.o 3.o -o $@
12: main.o 1.o 2.o; $(CC) main.o 1.o 2.o -o $@
13: main.o 1.o 3.o; $(CC) main.o 1.o 3.o -o $@
23: main.o 2.o 3.o; $(CC) main.o 2.o 3.o -o $@
/* ----  1.c ----- */
int num;
/* ----  2.c ----- */
extern int num;
/* ----  3.c ----- */
int num = 2;
/* ---- main.c --- */
#include <stdio.h>

extern int num;

int main() {
    printf("%d\n", num);
    return 0;
}

好,然后通过外科方式解构此SO归档文件,然后运行:

Ok, and after you have surgically deconstructed this SO-archive, and run:

make -i all
You should get an output something like:
cc main.o 2.o -o 2
Undefined symbols for architecture x86_64:
  "_num", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: [2] Error 1 (ignored)
./1
0
./2
make: ./2: No such file or directory
make: [all] Error 1 (ignored)
./3
2
./12
0
./13
2
./23
2

因此,首先,程序 2 无法构建。为什么不?因为2.c包含对外部变量(num)的显式声明;因此,当与main.c链接时,两者都对num表示了兴趣;

So, first up, the program 2 doesn't build. Why not? Because 2.c contains an explicit declaration of an external variable (num); so when linked with main.c, both have expressed an interest in num; but neither have defined it.

相反,。/ 1和./12都设法定义了它,但是没有为其分配值,因此将其定义为零。 1.c中缺少 extern 的特性为链接器耸了耸肩,说,好吧,我将在零部分(bss)中为其分配空间。

In contrast, both ./1 and ./12 have managed to define it, but have not assigned it a value, thus it is defined as zero. The lack of extern in 1.c provides the impetus for the linker to shrug and say, ok, I will just allocate space for it in the zero section (bss).

./ 3 ./13 ./23证明在存在定义语句(int num = 2;)的情况下,我们看到了预期的结果。

./3 ./13 ./23 demonstrate that in the presence of a defining statement (int num = 2;) we see the expected result.

遗漏了什么,但可能是一个很好的练习,如果您执行以下操作,将会发生以下情况:
$(CC)main.c 1.c 1.c 1.c 1.c -o 111 ?收到错误消息吗?为什么不呢?

What is left out, but may be a good exercise, is what happens if you: $(CC) main.c 1.c 1.c 1.c -o 111? Do you get an error? Why not?

这篇关于在某些情况下,链接器允许多个模块定义具有相同名称的全局符号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆