任何人都可以告诉我程序中实际发生堆栈溢出和堆溢出的原因和原因,以及如何克服编程中的堆栈溢出 - 如何避免它?
答案 0 :(得分:34)
void stack_overflow(const char *x)
{
char y[3];
strcpy(y, x);
}
void heap_overflow(const char *x)
{
char *y = malloc(strlen(x));
strcpy(y, x);
}
这两个函数都会超出分配的空间。
如果您呼叫stack_overflow("abc")
,它会将4个字符(包括空值)复制到分配给3个字符的空间中。之后会发生什么,取决于损坏的位置。变量y
在堆栈上,因此堆栈溢出。
无论你如何调用heap_overflow()
,它都会从堆中请求一个太少的字节,然后写入超出结尾。对此有点阴险的是,有些时候 - 甚至大部分时间 - 似乎都有效,因为堆系统分配的空间比你请求的多。但是,您可能会践踏控制数据,然后所有投注都会关闭。
堆溢出很小,很难检测到。堆栈溢出可能很小(如果传递的字符串足够短则不存在)或戏剧性。当您在分配的空间之外进一步写入时,通常会获得更多戏剧效果,但是超出分配空间的任何写入都会导致未定义的行为 - 任何事情都可能发生。
通过了解要复制的对象有多大以及有多少空间来接收它,并确保不复制比空间更多的材料,确保没有问题。总是,每一次。
答案 1 :(得分:4)
“堆栈溢出”与“基于堆栈的缓冲区溢出”不同。前者是由于激活记录太深,例如一个不间断的递归调用。后者是由于边界检查不足而导致的软件错误,这是最常被利用的漏洞。
答案 2 :(得分:-5)
堆栈溢出:
static void f(void) { f() ; }
int main() { f() ; }
堆溢出:
#include <stdlib.h>
int main() { while (1) malloc (1000) ; }
编辑显然这不是堆溢出的意思。见下面的评论。