完成使用后删除所有堆分配的内存是否切实可行?

时间:2018-06-13 23:03:02

标签: c++ c++11 heap heap-memory dynamic-memory-allocation

在使用完堆后,是否有任何特定情况下删除堆分配的内存是不实际也不必要的?或者不删除它总是在很大程度上影响程序?

3 个答案:

答案 0 :(得分:1)

在少数情况下,我有代码在堆上分配了很多东西。该程序的典型运行至少需要几个小时,而对于更大的数据集,这可能会持续几天左右。当它完成并退出程序时,所有析构函数都会运行,并释放所有内存。

但这导致了一些问题。特别是在长时间运行(在堆上分配了许多块)之后,所有析构函数运行大约需要五分钟。

所以,我重写了一些析构函数什么都不做 - 甚至没有一个对象分配的空闲内存。

该程序有一个非常简单的内存使用模式,因此它分配的所有内容在您关闭之前一直处于使用状态。禁用析构函数,使它们不再释放已分配的内存,将关闭程序的时间从约5分钟减少到即时出现的时间(但实际上仍然非常接近100毫秒)。

那就是说,这真的很少是一种选择。绝大多数时候,程序应该自行清理。使用编写良好的代码,无论如何它通常都是微不足道的。

答案 1 :(得分:1)

  

是否存在不实际的特定情况   完成后也不必删除堆分配的内存   使用它?

在某些类型的telecomm嵌入式系统中,我见过:

1)操作员命令软件修订更新也可以执行(或提醒用户执行)软件重置作为升级的最后一步。这不是功率反弹,并且(通常)相关的hw继续运行。

注意:有两种(或更多种)修订更新:1)处理器代码; 2)固件(通常存储在eprom中的fpga的固件)

在这种情况下,不需要删除长期堆分配的内存。我熟悉的嵌入式软件有许多新的数据结构,可以延续代码的生命周期。软件复位是用户命令的寿命终止,系统启动(不关闭)时内存为零。此时也没有使用dtor。

通常客户要求了解系统重新启动所需的时间上限。时间从客户想要的时候开始......也许是在下载新版本时...所以快速重置可以帮助实现额外的要求。

2)我曾在(嵌入式电信)系统上使用过看门狗'用于检测某些不一致的功能(包括线程'挂起')。此故障机制在某些持久性存储中生成日志条目(例如battery-back-static-ram或eprom或文件系统)。

日志条目是一些自我检测到的'不一致性。

任何删除堆内存的尝试都是可疑的,因为不一致可能已经损坏了系统。此重置不是用户命令,但可能具有基于站点策略的控件。此处还需要快速重置,以便在控制台上没有用户的情况下进行重置时恢复功能。

注意:

恕我直言,最有用的"开发功能"对于嵌入式系统(没有一个触发堆清理工作)是:

a)软复位开关(相当普遍的可用性) - 重新启动处理器,而不会影响软件控制/监控的hw。经常使用。

b)硬复位开关(可用性很少) - 电源弹出卡......处理器和它控制的设备,不会影响机架中的其他卡。 (未知效用。)

c)货架复位开关(有时货架上有自己的开关) - 电源反弹架子和所有卡,处理器和设备。这很少使用(除了系统启动问题),但另一种方法是笨拙地拔掉电源插头。

d)计算机控制这三个开关 - 我从未见过它。

答案 2 :(得分:0)

  

是否存在不实际的特定情况   完成后也不必删除堆分配的内存   使用它?

您分配且永不免费的任何堆内存将保持分配,直到您的进程退出。在此期间,没有其他程序可以将计算机RAM的那部分用于任何目的。

所以问题是,这会导致问题吗?答案取决于许多变量:

  1. 您的流程分配了多少内存?
  2. 计算机已实际安装了多少RAM并可供其他程序使用?
  3. 您的流程将持续运行多久(从而保留该内存)?
  4. 如果你的程序是运行的类型,它的东西,然后立即退出(或多或少),那么它可能没有“泄漏”内存的问题,因为泄漏的内存将被回收你的进程退出时的操作系统(注意:一些非常原始的/嵌入式/旧的操作系统可能无法回收已退出进程的资源,所以请确保你的操作系统确实 - 这就是说,几乎所有常用的现代操作系统都可以这样做)

    如果你的程序是可以无限期地继续运行的类型,那么内存泄漏将成为一个问题,因为如果程序不断分配内存并且永远不会释放内存,那么它最终会耗尽所有内存计算机可用的RAM然后坏事就会开始发生。

    一般来说,没有理由在现代C ++程序中泄漏内存 - 智能指针(例如out_fw =fellwalker(cube, rms, velax = 2,config['FellWalker_Noise'] = 2 ) std::unique_ptr)专门用于使内存泄漏变得容易避免使用它们比旧的/易泄漏的原始C指针更容易使用,因此没有理由不使用它们。