.globl -6ren">
gpt4 book ai didi

gcc - 在 g++ 中使用符号 '_end' 会导致段错误

转载 作者:行者123 更新时间:2023-12-02 06:47:51 25 4
gpt4 key购买 nike

考虑以下 C++ 源代码:

int _end[1050];

int main() {
for (int i = 0; i < 1050; i++)
_end[i] = 0;
return 0;
}

编译行:g++ main.cpp -o main -O0

在 Ubuntu 14.04 下使用 gcc-4.8.4 和 clang-3.6.0 时运行此代码会导致段错误。奇怪的行为是符号 _end 指向静态分配数组 _end 的末尾,而不是其开头。如果我们将 _end 替换为 end_,一切正常。

此外,如果我们通过提供 -S 命令行参数来要求 gcc 输出汇编代码,那么带有“_end”的版本和带有任何其他数组名称的版本之间不会有显着差异:

$ g++ main.cpp -o main.s -O0 -S
$ g++ main2.cpp -o main2.s -O0 -S
$ diff main.s main2.s
1,2c1,2
< .file "main.cpp"
< .globl _end
---
> .file "main2.cpp"
> .globl end_
5,7c5,7
< .type _end, @object
< .size _end, 4200
< _end:
---
> .type end_, @object
> .size end_, 4200
> end_:
25c25
< movl $0, _end(,%rax,4)
---
> movl $0, end_(,%rax,4)

但是,如果我们使用 objdump 转储可执行文件并对其运行 diff,我们将看到在 _end 版本中,使用的地址比所需的地址多 4200 = 4 * 1050 字节:

$ g++ main.cpp -o main -O0
$ g++ main2.cpp -o main2 -O0
$ objdump -d main >main.dump
$ objdump -d main2 > main2.dump
$ diff main.dump main2.dump
2c2
< main: формат файла elf64-x86-64 // "File format" in Russian
---
> main2: формат файла elf64-x86-64
123c123
< 4004ff: c7 04 85 c8 20 60 00 movl $0x0,0x6020c8(,%rax,4)
---
> 4004ff: c7 04 85 60 10 60 00 movl $0x0,0x601060(,%rax,4)

据我所知,gcc编译器可能会按照自己的意愿处理以下划线开头的变量,即: e.在代码中使用此类符号是一种不好的做法。但我的问题是:这里到底发生了什么?为什么 _end 被替换为已分配数组的末尾地址?为什么使用“-S”命令行参数没有区别,但创建的二进制文件实际上有区别?在这种情况下,gcc 和 clang 的行为并不相同,这对我来说也很奇怪。

最佳答案

_ 开头的 token 是保留的,您不应使用它们。看起来_end是为Linux上编译的程序定义的外部符号,表示未初始化数据段(也称为BSS段)末尾之后的第一个地址。

Note: On some systems the names of these symbols are preceded by underscores, thus: _etext, _edata, and _end.

来源:http://man7.org/linux/man-pages/man3/end.3.html

关于gcc - 在 g++ 中使用符号 '_end' 会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33760923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com