了解 C 中的数组声明
Understanding array declaration in C
我正在尝试了解 C 标准如何解释声明可能会导致错误。考虑以下非常简单的代码:
int main()
{
char test[1024 * 1024 * 1024];
test[0] = 0;
return 0;
}
这个段。但是下面的代码没有:
int main()
{
char test[1024 * 1024 * 1024];
return 0;
}
但是当我在我的机器上编译它时,最新的也出现了段错误。主要功能看起来像
00000000000008c6 <main>:
8c6: 55 push %rbp
8c7: 48 89 e5 mov %rsp,%rbp
8ca: 48 81 ec 20 00 00 40 sub [=12=]x40000020,%rsp
8d1: 89 bd ec ff ff bf mov %edi,-0x40000014(%rbp) // <---HERE
8d7: 48 89 b5 e0 ff ff bf mov %rsi,-0x40000020(%rbp)
8de: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
8e5: 00 00
8e7: 48 89 45 f8 mov %rax,-0x8(%rbp)
8eb: 31 c0 xor %eax,%eax
8ed: b8 00 00 00 00 mov [=12=]x0,%eax
8f2: 48 8b 55 f8 mov -0x8(%rbp),%rdx
8f6: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx
8fd: 00 00
8ff: 74 05 je 906 <main+0x40>
901: e8 1a fe ff ff callq 720 <__stack_chk_fail@plt>
906: c9 leaveq
907: c3 retq
908: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
90f: 00
据我所知,在尝试 mov %edi,-0x40000014(%rbp)
.
时发生了段错误
我试图在 N1570、Section 6.7.9 Initialization
中找到解释,但它似乎不是相关的。
那么标准是如何解释这种行为的?
结果取决于实现
我能想到行为应该不同的几个原因
- 编译器发现变量未被使用,没有可能的副作用,并对其进行优化(即使没有优化级别)
- 根据要求调整堆栈大小。由于还没有写入此变量,为什么现在调整堆栈大小?
- 编译器不必为自动内存使用堆栈。编译器可以使用
malloc
分配内存,并在退出时释放它。使用堆可以毫无问题地分配 1Gb
- 堆栈大小设置为 1Gb :)
我正在尝试了解 C 标准如何解释声明可能会导致错误。考虑以下非常简单的代码:
int main()
{
char test[1024 * 1024 * 1024];
test[0] = 0;
return 0;
}
这个段。但是下面的代码没有:
int main()
{
char test[1024 * 1024 * 1024];
return 0;
}
但是当我在我的机器上编译它时,最新的也出现了段错误。主要功能看起来像
00000000000008c6 <main>:
8c6: 55 push %rbp
8c7: 48 89 e5 mov %rsp,%rbp
8ca: 48 81 ec 20 00 00 40 sub [=12=]x40000020,%rsp
8d1: 89 bd ec ff ff bf mov %edi,-0x40000014(%rbp) // <---HERE
8d7: 48 89 b5 e0 ff ff bf mov %rsi,-0x40000020(%rbp)
8de: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
8e5: 00 00
8e7: 48 89 45 f8 mov %rax,-0x8(%rbp)
8eb: 31 c0 xor %eax,%eax
8ed: b8 00 00 00 00 mov [=12=]x0,%eax
8f2: 48 8b 55 f8 mov -0x8(%rbp),%rdx
8f6: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx
8fd: 00 00
8ff: 74 05 je 906 <main+0x40>
901: e8 1a fe ff ff callq 720 <__stack_chk_fail@plt>
906: c9 leaveq
907: c3 retq
908: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
90f: 00
据我所知,在尝试 mov %edi,-0x40000014(%rbp)
.
我试图在 N1570、Section 6.7.9 Initialization
中找到解释,但它似乎不是相关的。
那么标准是如何解释这种行为的?
结果取决于实现
我能想到行为应该不同的几个原因
- 编译器发现变量未被使用,没有可能的副作用,并对其进行优化(即使没有优化级别)
- 根据要求调整堆栈大小。由于还没有写入此变量,为什么现在调整堆栈大小?
- 编译器不必为自动内存使用堆栈。编译器可以使用
malloc
分配内存,并在退出时释放它。使用堆可以毫无问题地分配 1Gb - 堆栈大小设置为 1Gb :)