不删除动态分配的内存,并在程序终止后由操作系统释放

时间:2015-07-22 15:45:18

标签: c++ memory-management memory-leaks heap-memory

我已经阅读了这个问题和答案 dynamically allocated memory after program termination, 我想知道是否可以删除动态分配的内存并让它在程序终止后被操作系统释放。 那么,如果我为整个程序中需要的对象分配了一些内存,是否可以在程序结束时跳过删除它们,以使代码运行得更快?

3 个答案:

答案 0 :(得分:9)

简短的回答是肯定的,你可以,很长的答案可能你最好这样做:如果你的代码需要重构并变成库,你正在向那些打算做这项工作的人提供大量技术债务,这可能就是你。

此外,如果你有一个真实的,难以发现的内存泄漏(不是由于故意不释放长寿命对象而导致的内存泄漏),使用valgrind调试它会非常耗时噪音和误报量。

查看rectstd::shared_ptr。后者没有开销。

答案 1 :(得分:3)

大多数理智的操作系统在终止时释放进程所拥有的所有内存和本地资源(操作系统可能以懒惰方式执行,或减少其共享计数器,但在问题上并不重要)。因此,跳过释放这些资源是安全的。

然而,这是一个非常糟糕的习惯,你几乎什么也得不到。如果您发现释放对象需要很长时间(比如走在很长的对象列表中),您应该优化代码并选择更好的算法。

此外,虽然操作系统将释放所有本地资源,但是存在共享内存和全局空间信号量等异常,您需要明确释放它们。

答案 2 :(得分:-1)

首先,C ++中的头号规则是:

除非您真的需要,否则请避免动态分配!

不要轻易使用new;即使它安全地包裹在std::make_uniquestd::make_shared中也是如此。在C ++中创建类型实例的标准方法是:

T t;

在C ++中,只有当一个对象的寿命超过最初创建的范围时,才需要动态分配。

如果且仅当您需要动态分配对象时,请考虑使用std::shared_ptrstd::unique_ptr。当不再需要该对象时,这些将自动解除分配。

第二,

  

是否可以按顺序跳过在程序末尾删除它们   使代码运行得更快?

绝对不是,因为“才能使代码运行得更快”部分。这将是不成熟的优化。

这些是基本要点。

但是,您仍然需要考虑什么构成“真实”或坏内存泄漏。

这是一个糟糕的内存泄漏:

#include <iostream>

int main()
{
    int count;
    std::cin >> count;
    for (int i = 0; i < count; ++i)
    {
        int* memory = new int[100];
    }
}

这不错,因为记忆“永远丢失”;任何远程现代操作系统都会在过程结束后为您清理所有内容(请参阅Kerrek SB在您的链接问题中的答案)。

这很糟糕,因为内存消耗可能是不恒定的;随着用户输入,它将不必要地增长。

这是另一个糟糕的内存泄漏:

void OnButtonClicked()
{
    std::string* s = new std::string("my"); // evil!
    label->SetText(*s + " label");
}

这段(假想的,略显人为的)代码会使每次点击按钮都会增加内存消耗。程序运行的时间越长,所需的内存就越多。

现在将其与:

进行比较
int main()
{
    int* memory = new memory[100];
}

在这种情况下,内存消耗是恒定的;它不依赖于用户输入,并且程序运行的时间越长不会变大。虽然对于这么小的测试程序来说是愚蠢的,但在C ++中的情况,故意不能解除分配是有道理的。

想到了辛格尔顿。在C ++中实现Singleton的一个很好的方法是动态创建实例并永远不删除它;这避免了所有破坏顺序问题(例如SettingsManagerLog已被销毁时在其析构函数中写入Log。当操作系统清除内存时,不再执行代码并且您是安全的。

您可能永远不会遇到避免重新分配的好主意。但要警惕软件工程中的“永远”和“从不”规则,特别是在C ++中。良好的内存管理比将newdelete匹配要困难得多。