为什么在ELF中,外部变量的大小为0?

3
在 C 语言程序中,变量的外部声明导致在 ELF 中的大小为 0。当已知实际大小时,为什么不将其存储在 ELF 中?对于像不完整数组这样的情况,我理解没有大小信息,但对于其他情况,应该可以存储大小。
我尝试了一些简单代码,并验证了在 ELF 中发出的大小为零。
// file1.c

extern int var;
int main()
{
    var = 2;
}

// file 2.c
long long int var = 8;

gcc -c file1.c
readelf -s file1.o
...
9: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND var
...

gcc -c file2.c
readelf -s file2.o
...
7: 0000000000000000     8 OBJECT  GLOBAL DEFAULT    2 var
...

如果在file1.o中,变量var的大小被存储为4,那么当与file2.o进行链接时,链接器实际上可以检测到由于大小而导致的潜在不匹配。

那么为什么不发出大小以帮助捕捉这类微妙问题呢?


2
大小不是类型检查的良好替代品。一个 long longdouble 通常具有相同的大小,即 8。大小检查无法捕获将 extern long long x 定义为 double x 的情况。 - Kaz
关于不完整的数组,你提出了一个很好的观点!我本来也想写一下它,但是注意到你已经提到了它。 - Antti Haapala -- Слава Україні
@kaz,是的,在你提到的情况下,大小不足以满足要求,但比没有好。在目标文件中保持类型可能并非总是可行。我还发现,如果启用LTO,则可以捕获此类不匹配,因为使用-flto存储类型信息,并检测到不匹配并发出警告。 - user3575284
1个回答

6
file1中,var只是一个占位符,它不会占用任何内存。extern标识符是用来告诉编译器和链接器变量var存储在其他地方。
像你所建议的那样,为同一个变量var设置两个存储位置是错误的。
C语言的一个奇怪之处是你可以在外部变量定义不同类型并且底层全局变量的类型也不同,就像你在例子中做的一样。这就是我们有静态分析工具的原因之一。

虽然有一个常见的扩展,可以将未定义的符号与已定义的符号合并。 - Antti Haapala -- Слава Україні

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接