主函数中的return语句之前是否应该释放内存?

4

考虑这个小程序:

int main(int argc, const char *argv[])
{
    int *i = new int;
    //do something with i, where i is involved all the time
    return 0;
}

作为良好的风格,并且为了表明你确实知道,你必须释放在堆上分配的内存,通常在返回语句之前添加 delete i;
但如果忽略 delete i;,会有什么影响吗?
更新:请不要在评论中互相攻击。我知道为了安全起见,以及出于良好的风格等原因,应该释放已分配的内存。问题是,在这种特定情况下,是否可以安全地省略它。

操作系统会在程序退出时回收内存,所以从技术上讲,如果程序是这样退出的,你就不必释放它。但最好还是这样做。 - wkl
1
这种情况是智能指针的一个很好的应用场景。 - Seth Carnegie
1
这个问题过于局限,所以我投票关闭。在你的特定情况下(甚至不清楚你在什么操作系统上运行),答案可能是安全的。总的来说,这不是一个有见地的问题,答案也太分散了,没有任何价值。 - David Titarenco
如果您的情况与此完全相同,即在主函数中分配了一些自由存储空间,并且在返回之前可以选择是否“删除”它,那么您可以使用堆栈变量而不是自由存储变量和指向它的指针。 - Seth Carnegie
8个回答

5

由于现代操作系统在程序终止后倾向于清理程序的内存,所以这并不重要。话虽如此,我相当确定一些旧系统没有进行清理,因此如果你需要针对任何这些系统,请务必小心。

无论以上两点如何,让你的代码不泄漏难道不会让你睡得更安心吗?


4

不会有任何影响,因为系统会自动清除所有未删除的文件。
如果你编写的代码期望在程序终止之前使用所有内容,然后发现需要多次运行它,那么在迭代之间可能会存在内存泄漏问题。


3

没有什么危害。当进程死亡时,操作系统会释放所有进程的内存。

然而不删除变量是一种不好的风格,因为它会阻碍诸如Valgrind等工具的使用。


3
由于不知道上述操作系统运行的是哪个,因此这个答案可能是错误的或者完全不正确。 - David Titarenco
@DavidTitarenco,我理解你的观点。但是由于没有一个理智的人会在DSP/嵌入式系统上使用C++,我认为Roman B.想要在Windows >= 95或(某些,任何)*nix上运行他的代码。 - Kijewski
1
是的,我感兴趣的操作系统是最新的Windows和Linux。Valgrind是个不错的选择。 - Roman Byshko

2

在现代操作系统上,你的内存会被释放,但这并不意味着析构函数会被调用。

这是一种不好的做法,请不要这样做。使用智能指针代替。


1

如果您使用内存跟踪工具来查找内存泄漏,从顶层分配/释放不平衡的情况将显示为泄漏。这会分散您寻找真正内存泄漏的注意力。除此之外,您是安全的:操作系统会为您释放内存和其他资源。


1

大多数操作系统都会回收内存并将其捐赠给堆。但你会依赖这个吗?我认为你的具体例子看起来很无辜。是的,程序完成后,操作系统会夺回你忘记释放的所有内存。唯一的问题是,一旦你的程序变得更大并且能够服务于任何目的,并且有人让它运行,那么你基本上就是在“窃取”可能可用于其他正在运行的服务的内存。

a)永远不要浪费系统资源(内存、处理能力、端口、套接字等)

b)返回你不需要的任何东西,还有其他进程与你的同时运行。

我认为你建模的场景基本上依赖于你的应用程序被终止,这并不一定是必须的。


0

我认为在这个例子中不会有影响,因为程序无论如何都会退出,大多数操作系统应该会将该内存再次释放到堆上。但是你最好在使用变量后立即放置一个删除语句。


-4

如果您在调试模式下运行代码,分配的内存将被不同地跟踪,并且将在程序终止时释放。但是,如果您在发布模式下运行程序,则会导致内存泄漏,如果您一遍又一遍地运行程序,最终系统上的所有内存都将被分配并且不会被释放,从而导致低内存和其他所有糟糕的事情。

因此,这不仅仅是良好的编码风格。


4
你的回答是错误的。操作系统最终会进行内存清理。此外,大多数调试器不关心内存分配。跟踪指针的使用非常昂贵。如果不必要地使用,即使基本调试也会受到影响。 - Kijewski
我认为你所混淆的是内存的碎片化问题,这在长期运行中可能会发生。 - ch0kee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接