C-程序不会在堆溢出上崩溃



我写了以下程序:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(int argc, char *argv[]){
  char *input;
  input = (char*)malloc(16);
  printf("input is : %sn", input);
}

当我运行时:

./test `python -c 'print "A"*5000'`

它不会崩溃。它宁愿打印数据。

当我在printf之后使用free(input)时,它会崩溃。

为什么会发生这种情况?

所示代码忽略其命令行参数:

int main(int argc, char *argv[]){
  char *input;
  input = (char*)malloc(16);
  printf("input is : %sn", input);
}

Python脚本提供的内容无关紧要。但是,您的printf()正在打印非初始化的数据;这导致了不确定的行为。如果printf()没有崩溃,并且在printf()之后有free(input);调用,则free()不应崩溃。

如果您错过了副本操作并打算显示这样的内容,则规则是不同的:

int main(int argc, char *argv[]){
  char *input;
  input = (char*)malloc(16);
  strcpy(input, argv[1]);
  printf("input is : %sn", input);
  free(input);
  return 0;
}

现在,您没有在使用之前检查argv[1]不是零指针,而是可能导致崩溃。如果您在argv[1]中传递了5000个字符,则您将践踏分配的内存的界限。某些东西可能会触发崩溃;没有定义什么会导致崩溃。strcpy()可能会失败;printf()可能不会失败,如果副本没有(但不能保证);free()可能会失败,因为您从范围中踩踏了(但这也不能保证)。这就是"不确定行为"的奇观;一切都可能发生,这是有效的行为。

为什么会发生这种情况?

缓冲区溢出(在这种情况下,堆溢出)不会立即崩溃。在分配记忆的范围之外写作会导致不确定的行为 - 任何事情都可能发生;即使它也可以正常工作。

是否有一种可靠的方法来创建崩溃而没有免费()

如果您甚至不初始化指针input并将其取消(读或写入),最有可能您会得到一个segfault,但它仍然是"仅"未定义的行为。

来自C99标准草案

可能的未定义行为范围从忽略情况范围 完全具有不可预测的结果,在翻译过程中行为 或以记录的方式执行程序的特征 环境(有或没有发出诊断信息), 终止翻译或执行(发行 诊断消息)。


,但要小心

溢出可能会导致数据损坏或使用受影响的内存区域的任何过程。在没有内存保护的操作系统上,这可能是 System 的任何过程。

相关内容

  • 没有找到相关文章

最新更新