【发布时间】:2015-08-13 21:43:46
【问题描述】:
我用这个代码sn-p:
// stackoverflow.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char** argv)
{
int i;
int a[10];
// init
a[-1] = -1;
a[11] = 11;
printf(" a[-1]= = %d, a[11] = %d\n", a[-1], a[11]);
printf("I am finished.\n");
return a[-1];
}
编译器是 GCC for linux x86。它运行良好,没有任何运行时错误。我还在 Valgrind 中测试了这段代码,它也不会触发任何内存错误。
$ gcc -O0 -g -o stack_overflow stack_overflow.c
$ ./stack_overflow
a[-1]= = -1, a[11] = 11
I am finished.
$ valgrind ./stack_overflow
==3705== Memcheck, a memory error detector
==3705== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3705== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==3705== Command: ./stack_overflow
==3705==
a[-1]= = -1, a[11] = 11
I am finished.
==3705==
==3705== HEAP SUMMARY:
==3705== in use at exit: 0 bytes in 0 blocks
==3705== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==3705==
==3705== All heap blocks were freed -- no leaks are possible
==3705==
==3705== For counts of detected and suppressed errors, rerun with: -v
==3705== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
据我了解,堆和栈是同一种内存。唯一的区别是它们的生长方向相反。
所以我的问题是:
为什么堆上溢/下溢会触发 rum-time 错误,而堆栈上溢/下溢不会?
为什么 C 语言设计者没有像堆一样考虑到这一点,而是将其保留为 Undefined Behaviour
【问题讨论】:
-
这段代码不会触发堆栈溢出。尝试制作一个无限递归函数。
-
这简直就是 UB。 en.wikipedia.org/wiki/Undefined_behavior
-
Valgrind 应该已经捕获了超出数组末尾的写入。
-
因为很难知道 -1 的索引是堆栈不足/溢出!它未分配,但仍然存在,并且在极少数情况下进行这种访问是有效的(C++ 分配器可能会进行这种访问)。
-
必须 .. 查找 .. 重复 .. 'heap' 和 'stack' 是 physical 构造 - 将它们弄乱会导致 CPU 故障。这与您在这里所做的事情无关(嗯,很少)。您最后一个问题的最常见答案是,“因为由程序员确保不会发生这种情况”。 C 被设计为一种精益语言。
标签: c memory stack stackunderflow