我写了以下程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(int argc, char *argv[]){
char *input;
input = (char*)malloc(16);
printf("input is : %s\n", input);
}
当我将其作为:
运行时./test `python -c 'print "A"*5000'`
它没有崩溃。它打印数据。
当我在free(input)
之后使用printf
时,它会崩溃。
为什么会这样?
答案 0 :(得分:3)
显示的代码忽略了它的命令行参数:
int main(int argc, char *argv[]){
char *input;
input = (char*)malloc(16);
printf("input is : %s\n", input);
}
Python脚本提供的内容无关紧要。但是,您的printf()
正在打印未初始化的数据;这会导致未定义的行为。如果printf()
没有崩溃且free(input);
之后有printf()
次来电,则free()
不会崩溃。
如果您错过了复制操作并打算显示类似的内容,那么规则就不同了:
int main(int argc, char *argv[]){
char *input;
input = (char*)malloc(16);
strcpy(input, argv[1]);
printf("input is : %s\n", input);
free(input);
return 0;
}
现在你没有在使用之前检查argv[1]
是不是空指针 - 这可能会导致崩溃。如果你在argv[1]
中传递5000个字符,那么你正在践踏已分配内存的界限。有些东西可能会引发撞车;它没有定义会导致崩溃的原因。 strcpy()
可能会失败;如果副本没有(但不保证),printf()
可能不会失败; free()
可能会失败,因为你踩踏了界限(但即使这样也无法保证)。这就是“未定义行为”的奇迹;任何事都可能发生,这是有效的行为。
答案 1 :(得分:2)
为什么会这样?
缓冲区溢出(在这种情况下为heap overflow)不会立即导致崩溃。在分配的内存范围之外写入导致undefined behavior - 可能发生任何事情;即使它可以正常工作。
有没有可靠的方法来创建崩溃而没有free()
如果你甚至没有初始化指针input
并取消引用它(在那里读或写),很可能你将得到一个SEGFAULT,但它仍然是'仅'未定义的行为。
可能的未定义行为包括忽略这种情况 完全具有不可预测的结果,在翻译过程中表现出色 或者以文件化的方式执行程序 环境(有或没有发出诊断信息),到 终止翻译或执行(发布a 诊断信息)。
但要小心
溢出可能会导致任何使用受影响的内存区域的进程导致数据损坏或意外行为。在没有内存保护的操作系统上,这可以是系统上的任何过程。