为什么这行代码会导致计算机崩溃
Why does this line of code cause a computer to crash?
为什么这行代码会导致计算机崩溃?在特定于内存的级别会发生什么?
for(int *p=0; ;*(p++)=0)
;
我已经在 Everything2 上找到了"答案",但我想要一个具体的技术答案。
此代码只是将整数指针正式设置为 null,然后将它指向的整数写入 0 并递增指针,永远循环。
空指针不指向任何东西,因此向其写入 0 是未定义的行为(即标准没有说明应该发生什么(。此外,您不允许在数组外部使用指针算术,因此即使只是增量也是未定义的行为。
未定义的行为意味着编译器和库作者根本不需要关心这些情况,并且系统仍然是有效的 C/C++ 实现。如果程序员做了任何被归类为未定义行为的事情,那么无论发生什么,他/她都不能责怪编译器和库作者。进入未定义行为领域的程序员不能期待错误消息或崩溃,但如果得到一个(即使是后来执行了一百万条指令(,也不能抱怨。
在空指针表示为零并且不支持内存保护的系统上,效果或这样的循环可能是开始擦除所有可寻址内存,直到内存的某些重要部分(如中断表(损坏或直到代码在代码本身上写入零,自毁。在其他具有内存保护的系统上(当今最常见的桌面系统(,执行可能只是在第一次写入操作时停止。
> 毫无疑问,问题的原因是p
没有被分配一个合理的地址。
如果在写入指针指向的位置之前没有正确初始化指针,它可能会做坏事™。
它可能只是段错误,或者它可以覆盖一些重要的东西,比如函数的返回地址,在函数尝试返回之前不会发生段错误。
在 1980 年代,与我一起工作的一位理论家为 8086 编写了一个程序,每秒一次,在随机计算的地址上写入一个单词的随机数据。 计算机是一个过程控制器,具有看门狗保护和各种类型的输出。 问题是:系统在停止有效运行之前要运行多长时间? 答案是几个小时! 这生动地证明了大部分内存很少被访问。
它可能会导致操作系统崩溃,或者它可能会做任何其他事情。 您正在调用未定义的行为。您不拥有地址 0
的内存,也不拥有该地址过去的内存。 你只是在蹂躏不属于你的记忆。
它的工作原理是覆盖所有地址的所有内存,从 0 开始向上。最终它会覆盖一些重要的东西。
在任何现代系统上,这只会使您的程序崩溃,而不是整个计算机。自 1985 年左右以来设计的 CPU 具有称为虚拟内存的功能,它允许操作系统重定向程序的内存地址。大多数地址根本不定向到任何地方,这意味着尝试访问它们只会使您的程序崩溃 - 而定向到某个地方的地址将被定向到分配给程序的内存,因此您只能通过弄乱它们来崩溃自己的程序。
在更旧的系统上(记住,早于1985年!(,没有这样的保护,这个循环可以访问分配给其他程序和操作系统的内存地址。
解释问题所在的必要条件。我们只能简单地看一下第一次迭代。
int *p = 0; // Declare a null pointer
*p = 0; // Write to null pointer, causing UB
第二行导致未定义的行为,因为这就是写入空指针时发生的情况。
- 当回溯以零开始时,如何调试崩溃
- 内联映射初始化的动态atexit析构函数崩溃
- 执行函数时导致崩溃的变量
- 程序崩溃并显示"std::out_of_range"错误
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- CoInitialize()在单独的线程上崩溃而不返回
- EvtExportLogneneneba API正在将远程计算机的事件日志保存到远程PC本身.如何将其保存到主机
- 使用调试/崩溃报告将应用程序部署到客户端
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 为什么我的多线程作业队列崩溃
- ExtractIconEx:可以工作,但偶尔会崩溃
- 为什么引用传递会导致此崩溃(C++)
- Windows桌面程序保存您的计算机会话 - 基于程序崩溃时的恢复会话
- 视窗驱动程序IOCTL代码蓝屏/使计算机崩溃
- 如何检测终止进程事件、计算机关闭和计算机崩溃
- OpenCV人脸检测使计算机崩溃
- 使用删除会使我的计算机崩溃
- 为什么这行代码会导致计算机崩溃
- 访问计算机指针时发生访问冲突(c系统异常代码:c0000005),导致应用程序崩溃