可能是重复问题:
什么是堆栈溢出错误?
有人能告诉我堆栈溢出和堆溢出在程序中实际上是如何发生的,以及如何在编程中克服堆栈溢出-如何避免它?
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个字符 (包括 null 字符) 复制到为3个字符分配的空间中。之后会根据破坏产生的位置有所不同而导致不同的结果。变量 y
在堆栈上,因此它是堆栈溢出。
无论如何调用 heap_overflow()
,它都会从堆上请求一个字节太少并写入超出结尾的内容。这种情况的难以察觉之处在于,大多数时候它似乎能够正常工作,因为堆系统会分配比您请求的空间更多的空间。然而,您可能会踩到控制数据,那么结果将难以预料。
堆溢出非常小,很难检测。堆栈溢出可能很小(如果传递的字符串足够短则不存在),也可能非常明显。当您写入超出已分配空间的内容时,通常会产生更加明显的影响,但是任何超出已分配空间的写入都会导致未定义的行为——任何事情都可能发生。
您可以通过了解要复制的对象有多大以及接收它的空间有多少,确保没有问题,并确保您不会复制超过空间的材料。每次都一定要这样做。
堆栈溢出"与"基于堆栈的缓冲区溢出"不同。前者是由于太深的激活记录造成的,例如无休止的递归调用。后者是由于不充分的边界检查引起的软件漏洞,这是最常被利用的漏洞。
"堆栈溢出:
static void f(void) { f() ; }
int main() { f() ; }
堆溢出:
#include <stdlib.h>
int main() { while (1) malloc (1000) ; }
编辑 显然这不是堆栈溢出的意思。请参见下面的评论。
malloc
的头文件是stdlib.h
。memory.h
是另一个头文件。 - R.. GitHub STOP HELPING ICE
malloc(strlen(x))
,堆溢出会如何发生?难道这不应该精确地分配与用户输入相等的空间吗?我不明白。 - dlockstrlen(x)
不包括字符串末尾的空字节。如果您使用strcpy()
将x
复制到分配的内存中,则会多复制一个字节,可能会造成灾难性后果。 - Jonathan Leffler