用编程解释编程中的堆栈溢出和堆溢出?

mr_*_*air 15 c stack-overflow heap-memory

可能重复:
什么是堆栈溢出错误?

任何人都可以告诉我如何以及为什么在程序中实际发生堆溢出和堆溢出,以及如何克服编程中的堆栈溢出 - 如何避免它?

Jon*_*ler 34

堆栈溢出

void stack_overflow(const char *x)
{
    char y[3];
    strcpy(y, x);
}
Run Code Online (Sandbox Code Playgroud)

堆溢出

void heap_overflow(const char *x)
{
    char *y = malloc(strlen(x));
    strcpy(y, x);
}
Run Code Online (Sandbox Code Playgroud)

分析

这两个函数都会超出分配的空间.

如果您调用stack_overflow("abc"),它会将4个字符(包括空值)复制到分配给3个字符的空间中.之后会发生什么,取决于损坏的位置.变量y在堆栈上,因此堆栈溢出.

无论你如何调用heap_overflow(),它都会从堆中请求一个太少的字节,然后写入结束.对此有点阴险的是,有些时候 - 甚至大部分时间 - 似乎都有效,因为堆系统分配的空间比你请求的多.但是,您可能会践踏控制数据,然后所有投注都会关闭.

堆溢出很小,很难检测到.堆栈溢出可能很小(如果传递的字符串足够短则不存在)或戏剧性.当您在分配的空间之外进一步写入时,通常会获得更多戏剧效果,但是超出分配空间的任何写入都会导致未定义的行为 - 任何事情都可能发生.

您可以通过了解要复制的对象有多大以及接收它的空间来确保没有问题,并确保不复制比空间更多的材料.总是,每一次.

  • 关于“堆栈溢出”和“堆溢出”的含义有两种观点。本答案中所示的一种变体是缓冲区溢出,即您在缓冲区(内存块)的边界之外写入(或读取)。另一种变体是资源耗尽,即您尝试使用比可用空间更多的空间。特别是,堆栈是一种有限的资源(通常只有 8 MiB,在某些系统上甚至更少),因此在堆栈上创建大型基于堆栈的变量(例如数组)可能会导致麻烦。使用虚拟内存,更难耗尽堆,但内存泄漏也会造成这种情况。 (3认同)

Inf*_*ite 5

“堆栈溢出”与“基于堆栈的缓冲区溢出”不同。前者是由于激活记录太深,例如不间断的递归调用。后者是由于边界检查不充分而导致的软件错误,是最常被利用的漏洞。