C++ 为什么我需要删除[]?

C++ 为什么我需要删除[]?,c++,memory,memory-management,memory-leaks,delete-operator,C++,Memory,Memory Management,Memory Leaks,Delete Operator,假设我有这样一个函数: int main() { char* str = new char[10]; for(int i=0;i<5;i++) { //Do stuff with str } delete[] str; return 0; } intmain() { char*str=新字符[10]; 对于(int i=0;i是的,这是一个很好的做法。你永远不要认为你的操作系统会处理你的内存释放,如果你养成了这个习惯,以

假设我有这样一个函数:

int main()
{
    char* str = new char[10];

    for(int i=0;i<5;i++)
    {
        //Do stuff with str
    }

    delete[] str;
    return 0;
}
intmain()
{
char*str=新字符[10];

对于(int i=0;i是的,这是一个很好的做法。你永远不要认为你的操作系统会处理你的内存释放,如果你养成了这个习惯,以后会让你倒霉的


但是,为了回答您的问题,在退出主进程时,操作系统会释放该进程持有的所有内存,包括您可能产生的任何线程或分配的变量。操作系统将负责释放该内存供其他人使用。

您的操作系统应负责该内存,并在退出时将其清理干净我个人认为,最好是进入正确的思维方式,因为当你在做简单的程序时,你最有可能这样做是为了学习


不管是哪种方式,保证内存释放的唯一方法是自己这样做。

相反的答案:不,这是浪费时间。一个有大量分配数据的程序几乎必须接触每一页才能将所有分配返回到空闲列表。这浪费了CPU时间,给UNTO造成了内存压力休眠数据,甚至可能导致进程从磁盘交换回页面。只需退出即可将所有内存释放回操作系统,无需任何进一步操作


(并不是说我不同意“是”中的理由,我只是认为两者都有争议)重要提示:
delete
释放内存几乎只是一个副作用。它所做的重要事情是破坏对象。对于RAII设计,这可能意味着关闭文件、释放操作系统句柄、终止线程或删除临时文件

当进程退出时,操作系统会自动处理其中一些操作,但不是全部

在您的示例中,没有理由不调用
delete
。但是也没有理由调用
new
,因此您可以通过这种方式避开这个问题

char str[10];
或者,您可以使用智能指针避开删除(以及涉及的异常安全问题)

因此,一般来说,您应该始终确保对象的生命周期得到正确管理


但这并不总是容易的:解决问题的办法通常意味着你别无选择,只能依靠操作系统为你清理一些单例类型的对象。

如果事实上你的问题真的是“我有一个简单的程序,在它退出之前我不释放几个字节行吗?”答案是肯定的,这很好。在任何现代操作系统上,这都会很好。而且这个程序很简单;不像你要用这个东西把它放进起搏器或运行丰田凯美瑞的制动系统。如果唯一的客户是你,那么你唯一可能因为马虎而受到影响的人就是你

当你开始从这个问题的答案中归纳出非平凡案例时,问题就来了

因此,让我们来问两个关于一些非平凡案例的问题

我有一个长期运行的服务,它以复杂的方式分配和释放内存,可能涉及多个分配器命中多个堆。在正常模式下关闭我的服务是一个复杂而耗时的过程,需要确保外部状态(文件、数据库等)一致关闭。我应该在我关机之前,我分配的内存的每个字节都被释放了吗

是的,我会告诉你原因。长期运行的服务可能发生的最糟糕的事情之一是它意外泄漏内存。随着时间的推移,即使是很小的泄漏也会累积成巨大的泄漏。查找和修复内存泄漏的一种标准技术是检测分配堆,以便在关闭时记录所有被占用的资源在没有释放的情况下定位。除非您喜欢追踪大量误报并在调试器中花费大量时间,否则请始终释放内存,即使严格来说没有必要这样做

用户已经期望关闭服务可能需要数十亿纳秒,所以谁在乎你是否会对虚拟分配器造成一点额外的压力,确保所有东西都被清理干净呢?这只是你为大型复杂软件付出的代价。而且你并不是一直关闭服务,所以艾恩,谁在乎它是否比可能的慢几毫秒

我有同样的长期运行服务。如果我检测到我的一个内部数据结构损坏,我希望“快速失败”。该程序处于未定义状态,它可能以提升的权限运行,我假设如果我检测到损坏的状态,这是因为我的服务正受到敌对方的主动攻击。最安全的做法是立即关闭服务。我宁愿让攻击者拒绝为客户端提供服务han不得不冒着服务无法正常运行和进一步破坏用户数据的风险。在这种紧急关闭场景中,我应该确保分配的每个字节的内存都被释放吗

当然不是。操作系统会帮你解决这个问题。如果你的堆损坏了,攻击者可能希望你释放内存作为他们利用的一部分。每毫秒都很重要。你为什么要在对大楼投下战术核弹之前费心擦门把手和厨房呢


因此,“我应该在程序退出之前释放内存吗?”这一问题的答案是“这取决于您的程序的功能”。

我非常同意Eric Lippert的建议:

所以“我应该在程序退出之前释放内存吗?”这个问题的答案是“这取决于您的程序的功能”。

这里的其他答案提供了支持和反对这两种观点的论据,但这是问题的真正症结所在
int main()
{

    while(1)
    { 
        char* str = new char[10];

        for(int i=0;i<5;i++)
        {
            //Do stuff with str
        }
    }

    delete[] str;
    return 0;
}
Allocation Myth 4: Non-garbage-collected programs should always deallocate all memory they allocate. The Truth: Omitted deallocations in frequently executed code cause growing leaks. They are rarely acceptable. but Programs that retain most allocated memory until program exit often perform better without any intervening deallocation. Malloc is much easier to implement if there is no free. In most cases, deallocating memory just before program exit is pointless. The OS will reclaim it anyway. Free will touch and page in the dead objects; the OS won't. Consequence: Be careful with "leak detectors" that count allocations. Some "leaks" are good! Think about your class 'A' having to deconstruct. If you don't call 'delete' on 'a', that destructor won't get called. Usually, that won't really matter if the process ends anyway. But what if the destructor has to release e.g. objects in a database? Flush a cache to a logfile? Write a memory cache back to disk? **You see, it's not just 'good practice' to delete objects, in some situations it is required**.