C语言 当您退出 C 应用程序时,是否会自动释放 malloc 处理的内存?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2213627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When you exit a C application, is the malloc-ed memory automatically freed?
提问by Andreas Grech
Let's say I have the following C code:
假设我有以下 C 代码:
int main () {
int *p = malloc(10 * sizeof *p);
*p = 42;
return 0; //Exiting without freeing the allocated memory
}
When I compile and execute that C program, ie after allocating some space in memory, will that memory I allocated be still allocated (ie basically taking up space) after I exit the application and the process terminates?
当我编译并执行那个 C 程序时,即在内存中分配了一些空间后,在我退出应用程序并且进程终止后,我分配的内存是否仍然被分配(即基本上占用空间)?
回答by Yacoby
It depends on the operating system. The majority of modern (and all major) operating systems will free memory not freed by the program when it ends.
这取决于操作系统。大多数现代(和所有主要)操作系统将释放程序结束时未释放的内存。
Relying on this is bad practice and it is better to free it explicitly. The issue isn't just that your code looks bad. You may decide you want to integrate your small program into a larger, long running one. Then a while later you have to spend hours tracking down memory leaks.
Relying on a feature of an operating system also makes the code less portable.
依赖这个是不好的做法,最好明确地释放它。问题不仅仅是您的代码看起来很糟糕。您可能决定将您的小程序集成到一个更大的、长时间运行的程序中。然后一段时间后,您必须花费数小时来跟踪内存泄漏。
依赖操作系统的功能也会降低代码的可移植性。
回答by Kevin Reid
In general, modern general-purpose operating systems do clean up after terminated processes. This is necessary because the alternative is for the system to lose resources over time and require rebooting due to programs which are poorly written or simply have rarely-occurring bugs that leak resources.
一般来说,现代通用操作系统会在终止进程后进行清理。这是必要的,因为替代方案是系统随着时间的推移丢失资源,并且由于程序编写不当或只是很少发生泄漏资源的错误而需要重新启动。
Having your program explicitly free its resources anyway can be good practicefor various reasons, such as:
出于各种原因,让您的程序显式释放其资源可能是一种很好的做法,例如:
- If you have additional resources that are notcleaned up by the OS on exit, such as temporary files or any kind of changeto the state of an external resource, then you will need code to deal with all of those things on exit, and this is often elegantly combined with freeing memory.
- If your program starts having a longer lifetime, then you will not want the onlyway to free memory to be to exit. For example, you might want to convert your program into a server (daemon) which keeps running while handling many requests for individual units of work, or your program might become a small part of a larger program.
- 如果您有其他资源在退出时未被操作系统清理,例如临时文件或对外部资源状态的任何类型的更改,那么您将需要代码来处理退出时的所有这些事情,这通常与释放内存优雅地结合在一起。
- 如果您的程序开始有更长的生命周期,那么您不会希望释放内存的唯一方法是退出。例如,您可能希望将您的程序转换为一个服务器(守护进程),该服务器在处理单个工作单元的许多请求时保持运行,或者您的程序可能成为更大程序的一小部分。
However, here is a reason to skip freeing memory: efficient shutdown. For example, suppose your application contains a large cache in memory. If when it exits it goes through the entire cache structure and frees it one piece at a time, that serves no useful purpose and wastes resources. Especially, consider the case where the memory pages containing your cache have been swapped to disk by the operating system; by walking the structure and freeing it you're bringing all of those pages back into memory all at once, wasting significant time and energy for no actual benefit, and possibly even causing other programs on the system to get swapped out!
但是,这里有一个跳过释放内存的原因:高效关机。例如,假设您的应用程序在内存中包含一个大缓存。如果它退出时遍历整个缓存结构并一次释放一个,那将没有任何用处并且浪费资源。尤其要考虑包含缓存的内存页已被操作系统交换到磁盘的情况;通过遍历结构并释放它,您将所有这些页面同时带回内存,浪费了大量时间和精力而没有实际好处,甚至可能导致系统上的其他程序被换出!
As a related example, there are high-performance servers that work by creating a process for each request, then having it exit when done; by this means they don't even have to track memory allocation, and never do any freeing or garbage collection at all, since everything just vanishes back into the operating system's free memory at the end of the process. (The same kind of thing can be done within a process using a custom memory allocator, but requires very careful programming; essentially making one's own notion of “lightweight processes” within the OS process.)
作为一个相关的例子,有一些高性能服务器通过为每个请求创建一个进程来工作,然后在完成后退出;这意味着他们甚至不必跟踪内存分配,并且根本不进行任何释放或垃圾收集,因为一切都在进程结束时消失回操作系统的空闲内存中。(同样的事情可以在使用自定义内存分配器的进程中完成,但需要非常仔细的编程;本质上是在操作系统进程中创建自己的“轻量级进程”概念。)
回答by Wes Miller
My apologies for posting so long after the last post to this thread.
我很抱歉在这个线程的最后一个帖子之后发布这么长时间。
One additional point. Not all programs make it to graceful exits. Crashes and ctrl-C's, etc. will cause a program to exit in uncontrolled ways. If your OS did not free your heap, clean up your stack, delete static variables, etc, you would eventually crash your system from memory leaks or worse.
补充一点。并非所有程序都能正常退出。崩溃和 ctrl-C 等会导致程序以不受控制的方式退出。如果您的操作系统没有释放您的堆、清理您的堆栈、删除静态变量等,您最终会因内存泄漏或更糟而使您的系统崩溃。
Interesting aside to this, crashes/breaks in Ubuntu, and I suspect all other modern OSes, do have problems with "handled' resources. Sockets, files, devices, etc. can remain "open" when a program ends/crashes. It is also good practice to close anything with a "handle" or "descriptor" as part of your clean up prior to graceful exit.
有趣的是,在 Ubuntu 中崩溃/中断,我怀疑所有其他现代操作系统在“处理”资源方面确实存在问题。当程序结束/崩溃时,套接字、文件、设备等可以保持“打开”状态。它是在正常退出之前,作为清理的一部分,使用“句柄”或“描述符”关闭任何内容也是一种很好的做法。
I am currently developing a program that uses sockets heavily. When I get stuck in a hang I have to ctrl-c out of it, thus, stranding my sockets. I added a std::vector to collect a list of all opened sockets and a sigaction handler that catches sigint and sigterm. The handler walks the list and closes the sockets. I plan on making a similar cleanup routine for use before throw's that will lead to premature termination.
我目前正在开发一个大量使用套接字的程序。当我陷入挂起时,我必须 ctrl-c 离开它,因此,搁浅了我的套接字。我添加了一个 std::vector 来收集所有打开的套接字的列表和一个捕获 sigint 和 sigterm 的 sigaction 处理程序。处理程序遍历列表并关闭套接字。我计划在抛出之前使用类似的清理例程,这将导致过早终止。
Anyone care to comment on this design?
有人愿意评论这个设计吗?
回答by Ben Zotto
What's happening here (in a modern OS), is that your program runs inside its own "process." This is an operating system entity that is endowed with its own address space, file descriptors, etc. Your malloccalls are allocating memory from the "heap", or unallocated memory pages that are assigned to your process.
这里(在现代操作系统中)发生的事情是您的程序在它自己的“进程”中运行。这是一个操作系统实体,具有自己的地址空间、文件描述符等。您的malloc调用正在从“堆”或分配给您的进程的未分配内存页中分配内存。
When your program ends, as in this example, all of the resources assigned to your process are simply recycled/torn down by the operating system. In the case of memory, all of the memory pages that are assigned to you are simply marked as "free" and recycled for the use of other processes. Pages are a lower-level concept than what malloc handles-- as a result, the specifics of malloc/free are all simply washed away as the whole thing gets cleaned up.
当你的程序结束时,就像在这个例子中一样,分配给你的进程的所有资源都会被操作系统简单地回收/拆除。在内存的情况下,所有分配给您的内存页面都被简单地标记为“空闲”并回收以供其他进程使用。页面是一个比 malloc 处理的更低级的概念——因此,随着整个事情被清理干净,malloc/free 的细节都被简单地洗掉了。
It's the moral equivalent of, when you're done using your laptop and want to give it to a friend, you don't bother to individually delete each file. You just format the hard drive.
这在道德上等同于,当您使用完笔记本电脑并想将其送给朋友时,您不必费心单独删除每个文件。您只需格式化硬盘驱动器。
All this said, as all other answerers are noting, relying on this is not good practice:
所有这一切都说,正如所有其他回答者所指出的那样,依赖这不是一个好习惯:
- You should always be programming to take care of resources, and in C that means memory as well. You might end up embedding your code in a library, or it might end up running much longer than you expect.
- Some OSs (older ones and maybe some modern embedded ones) may not maintain such hard process boundaries, and your allocations might affect others' address spaces.
- 您应该始终通过编程来处理资源,在 C 中这也意味着内存。您可能最终将代码嵌入到一个库中,或者它的运行时间可能比您预期的要长得多。
- 某些操作系统(较旧的操作系统,可能还有一些现代嵌入式操作系统)可能不会保持这样的硬进程边界,并且您的分配可能会影响其他人的地址空间。
回答by Mark Wilkins
Yes. The OS cleans up resources. Well ... old versions of NetWare didn't.
是的。操作系统清理资源。嗯……旧版本的 NetWare 没有。
Edit: As San Jacinto pointed out, there are certainly systems (aside from NetWare) that do not do that. Even in throw-away programs, I try to make a habit of freeing all resources just to keep up the habit.
编辑:正如圣哈辛托指出的那样,肯定有系统(除了 NetWare)不这样做。即使在一次性程序中,我也尝试养成释放所有资源的习惯,以保持这种习惯。
回答by Charles
It depends, operating systems will usually clean it up for you, but if you're working on for instance embedded software then it might not be released.
这取决于,操作系统通常会为您清理它,但如果您正在开发嵌入式软件,那么它可能不会发布。
Just make sure you free it, it can save you a lot of time later when you might want to integrate it in to a large project.
只要确保你释放它,当你想将它集成到一个大型项目中时,它可以为你节省很多时间。
回答by Draemon
Yes, the operating system releases all memory when the process ends.
是的,操作系统会在进程结束时释放所有内存。
回答by Draemon
I think direct freeing is best. Undefined behaviour is the worst thing, so if you have access while it's still defined in your process, do it, there are lots of good reasons people have given for it.
我认为直接释放是最好的。未定义的行为是最糟糕的事情,因此如果您在流程中仍然定义的情况下可以访问,请执行此操作,人们为此给出了很多很好的理由。
As to where, or whether, I found that in W98, the real question was 'when' (I didn't see a post emphasising this). A small template program (for MIDI SysEx input, using various malloc'd spaces) would free memory in the WM_DESTROY bit of the WndProc, but when I transplanted this to a larger program it crashed on exit. I assumed this meant I was trying to free what the OS had already freed during a larger cleanup. If I did it on WM_CLOSE, then called DestroyWindow(), it all worked fine, instant clean exit.
至于在哪里或是否在 W98 中发现,真正的问题是“何时”(我没有看到强调这一点的帖子)。一个小的模板程序(用于 MIDI SysEx 输入,使用各种 malloc 空间)将释放 WndProc 的 WM_DESTROY 位中的内存,但是当我将它移植到一个更大的程序时,它在退出时崩溃了。我认为这意味着我试图释放操作系统在更大的清理过程中已经释放的内容。如果我在 WM_CLOSE 上执行此操作,然后调用 DestroyWindow(),则一切正常,立即干净退出。
While this isn't exactly the same as MIDI buffers, there is similarity in that it is best to keep the process intact, clean up fully, then exit. With modest memory chunks this is very fast. I found that many small buffers worked faster in operation and cleanup than fewer large ones.
虽然这与 MIDI 缓冲区不完全相同,但它们的相似之处在于最好保持进程完整,彻底清理,然后退出。使用适度的内存块,这是非常快的。我发现许多小缓冲区在操作和清理方面比较少的大缓冲区工作得更快。
Exceptions may exist, as someone said when avoiding hauling large memory chunks back out of a swap file on disk, but even that may be minimised by keeping more, and smaller, allocated spaces.
正如有人在避免从磁盘上的交换文件中取出大内存块时所说的那样,可能存在例外情况,但即使这样也可以通过保留更多和更小的分配空间来最小化。
回答by Draemon
That really depends on the operating system, but for all operating systems you'll ever encounter, the memory allocation will disappear when the process exits.
这确实取决于操作系统,但对于您将遇到的所有操作系统,当进程退出时,内存分配将消失。

