用例子解释编程中的栈溢出和堆溢出? [复制]

Posted

技术标签:

【中文标题】用例子解释编程中的栈溢出和堆溢出? [复制]【英文标题】:Explain stack overflow and heap overflow in programming with example? [duplicate] 【发布时间】:2011-06-09 17:11:38 【问题描述】:

可能重复:What is a stack overflow error?

谁能告诉我程序中实际发生堆栈溢出和堆溢出的方式和原因,以及如何克服编程中的堆栈溢出-如何避免?

【问题讨论】:

【参考方案1】:

堆栈溢出

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(),它都会从堆中请求一个太少的字节,然后写入超出末尾。阴险的是,在某些时候——甚至大部分时间——它似乎会起作用,因为堆系统分配的空间比你请求的要多。但是,您可能会践踏控制数据,然后所有赌注都被取消。

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

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

【讨论】:

对于“堆栈溢出”和“堆溢出”的含义有两种看法。一种变体,即此答案中说明的变体,是缓冲区溢出,您在缓冲区(内存块)边界之外写入(或读取)。另一种变体是资源耗尽,您尝试使用比可用空间更多的空间。特别是堆栈是一种有限资源(通常只有 8 MiB,在某些系统上甚至更少),因此在堆栈上创建基于堆栈的大型变量(例如数组)可能会导致麻烦。使用虚拟内存,更难用完堆,但内存泄漏也可以做到这一点。 你说“堆系统分配的空间比你请求的多”。你能提供一些很好的参考/文章,这对我有更多的解释吗? @user2393267:如果你找到malloc() 的任何示例实现,你可能会发现它将N 字节的请求四舍五入为((N + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE 字节,因此请求是内部块大小(在 32 位或 64 位系统上通常分别为 8 或 16 个字节)。在请求的内存之前存储有关分配大小的信息也是很常见的,这样当它被释放时,free() 可以知道最初分配了多大的块。所以计算很可能比上面的数字多出一个 BLOCK_SIZE。 @user2393267:malloc() 的示例实现在 K&R 第 2 版(或第 1 版)中,但您不应该使用它——尽管它在我的个人库中占有重要地位,因为它我买的时候是最新的)。毫无疑问,您可以在网上找到许多其他工具(Linux GLIBC、BSD、dlmalloc 等等)。 如果我们这样做malloc(strlen(x)),堆溢出会如何发生。那分配空间不应该完全等于用户输入吗?没看懂【参考方案2】:

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

【讨论】:

【参考方案3】:

堆栈溢出:

 static void f(void)  f() ; 
 int main()  f() ; 

堆溢出:

 #include <stdlib.h>
 int main()  while (1) malloc (1000) ; 

编辑显然这不是堆溢出的意思。请参阅下面的 cmets。

【讨论】:

那些显示堆栈耗尽和堆耗尽,但不显示堆栈溢出或堆溢出。 -1 表示错误答案和memory.hmalloc 的标头是 stdlib.h @Jonathan Leffler:我认为堆栈溢出是正确的。对于它的价值,*** (en.wikipedia.org/wiki/Stack_overflow) 支持我(文章将您的概念描述为“堆栈缓冲区溢出”)。但是你说的堆溢出是对的。 如果你区分'堆栈溢出'和'堆栈缓冲区溢出',那么你的堆栈溢出代码最终会耗尽堆栈(这也是'耗尽'),但这也可以视为溢出.很多时候,堆栈溢出被用作堆栈缓冲区溢出的简写,而您的示例并未说明这一点。所以,我可以将您的堆栈溢出称为堆栈溢出的一种变体的示例。

以上是关于用例子解释编程中的栈溢出和堆溢出? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出

五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出

栈溢出原理

有人可以解释一下这个例子中 CSS 中的“溢出”到底对背景做了啥吗? [复制]

栈溢出攻击系列:shellcode在linux x86 64位攻击获得root权限固定地址的栈溢出攻击

java栈内存溢出怎么解决