【问题标题】:What would declaring a pointer with the "new" operator within a while loop do to my computer?在 while 循环中使用“new”运算符声明指针对我的计算机有什么影响?
【发布时间】:2021-08-17 05:03:22
【问题描述】:

所以我最近开始学习 C++,我对内存分配、垃圾收集、堆、堆栈等非常感兴趣......

我写了这个程序,我想知道它会对我的电脑做什么?它会因为我的 RAM 被填满而崩溃吗?它会运行得更慢吗?它会在它填满太多内存之前停止吗?

我太害怕在我的机器上运行它了。

#include <iostream>
using namespace std;

int main()
{
    while (true) {
        int* x = new int;
    }
}

编辑:

所以我在我的电脑上运行了这个程序,它实际上只是一个吃公羊的程序。我一直在运行,直到 Windows 资源管理器失败并且我的桌面变黑。然后我重启了电脑,一切正常。

【问题讨论】:

  • 当操作系统不准备为您提供更多内存时,您的new 将失败并出现异常。

标签: c++ garbage-collection dynamic-memory-allocation


【解决方案1】:

它实际上取决于运行程序的主机系统和编译器。

一些编译器(尤其是启用了优化设置)足够聪明,可以识别循环中分配的内存没有以影响程序输出的方式使用。然后编译器可能会忽略内存分配,然后(因为在 C++ 中什么都不做的无限循环实际上会产生未定义的行为)可以做任何事情。可能的结果包括程序永远循环(消耗 CPU 周期但不分配内存),编译器根本不生成循环(因此程序立即终止)。

如果编译器优化没有发挥作用(例如未优化的构建),程序可能会循环并重复分配内存。然后会发生什么取决于操作系统。

某些操作系统(例如 unix 变体)可以配置(或默认配置)进行延迟分配或过度提交,在某种意义上,它们实际上不会分配虚拟或物理内存,直到程序尝试 非平凡地使用该内存(例如在其中存储数据)。由于您的循环从不使用它分配的内存,因此在执行惰性分配的系统上,循环可能会无限期地运行 - 除了丢失 CPU 周期外,对主机系统没有明显的影响。

如果操作系统没有配置为惰性分配(例如实际上立即分配内存),循环将继续直到分配失败并通过抛出异常终止程序。

在此过程中发生的事情再次取决于操作系统。

如果操作系统对进程施加的配额限制显着小于操作系统可用的总内存(物理或虚拟),那么其他进程(以及操作系统本身)可能不受我们程序的影响。

如果操作系统允许程序分配所有可用内存,那么这个程序中的重复分配可能会影响其他程序的行为,或者操作系统本身。如果操作系统能够检测到这一点,它可能会强制终止程序 - 并且在该过程中,它可能回收分配的内存。如果操作系统没有检测到该行为并终止程序,则该程序可能会导致操作系统变慢。

如果您的操作系统本身是托管的(例如在管理程序环境中),那么操作系统本身可能会被终止,但在同一物理机器上运行的其他操作系统实例通常不会受到影响。

至少已经有二十年了,新手程序员可以在毫无戒心的机器上释放这样的程序,甚至对机器最终会变慢并可能崩溃,或者需要一个硬电源循环有一点信心。操作系统设计和更大的系统设计(例如管理程序的常规使用)使得此类恶作剧不太可能产生任何持久影响。

【讨论】:

  • 运行时必须记住分配(使用new int时可能需要比实际int更多的空间),因此惰性分配可能无法防止内存耗尽。
【解决方案2】:

你首先要面对的是memory leak

但您的程序将继续从堆中分配内存并面临内存泄漏,但操作系统会停止您的程序。操作系统中有一个名为OOM 的概念。在这个概念中,如果某些程序继续分配内存并导致系统的某些重要部分出现故障,操作系统将立即发送SIGKILL 信号。这是导致您程序被杀死然后释放分配的内存。

【讨论】:

  • 所以你说用SIGKILL杀死程序后,释放内存。这是否意味着在堆中无法再访问的所有分配的“新”整数都被清除了?还是需要重启电脑才能清除?
  • 其实我想我在这里找到了后续的答案stackoverflow.com/questions/15882531/…
  • @heartgg 不需要重新启动。操作系统会处理这些内存。但请注意,无论何时运行程序,都可以使用 Ctrl^c、Ctrl^z 或 kill 之类的命令(至少在 linux 中)来终止该程序。所以不用担心操作系统会处理所有问题。
  • 程序进程被终止并清空并分配的堆内存返回给操作系统。
  • 不正确。 C++ 标准说在这种情况下你会得到一个例外; C标准说malloc()和朋友会返回null; ENOMEM 到底是干什么用的?
猜你喜欢
  • 1970-01-01
  • 2021-12-16
  • 2012-01-30
  • 2014-05-18
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-11
相关资源
最近更新 更多