我们都被教导必须释放每个已分配的指针。不过,我有点好奇不释放内存的真正代价。在一些明显的情况下,比如在循环内部或线程执行的一部分调用malloc()时,释放是非常重要的,这样就不会有内存泄漏。但是考虑下面两个例子:

首先,如果我有这样的代码:

int main()
{
    char *a = malloc(1024);
    /* Do some arbitrary stuff with 'a' (no alloc functions) */
    return 0;
}

真正的结果是什么?我的想法是进程死亡,然后堆空间也消失了,所以错过对free的调用没有什么坏处(然而,我确实认识到无论如何拥有它对于闭包、可维护性和良好实践的重要性)。我这样想对吗?

Second, let's say I have a program that acts a bit like a shell. Users can declare variables like aaa = 123 and those are stored in some dynamic data structure for later use. Clearly, it seems obvious that you'd use some solution that will calls some *alloc function (hashmap, linked list, something like that). For this kind of program, it doesn't make sense to ever free after calling malloc because these variables must be present at all times during the program's execution and there's no good way (that I can see) to implement this with statically allocated space. Is it bad design to have a bunch of memory that's allocated but only freed as part of the process ending? If so, what's the alternative?


当前回答

我完全不同意那些说OP是正确的或没有伤害的人。

每个人都在谈论现代和/或传统的操作系统。

但是如果我在一个没有操作系统的环境中呢? 哪里什么都没有?

想象一下,现在您正在使用线程样式的中断并分配内存。 在C标准ISO/IEC:9899中,内存的寿命表示为:

7.20.3 Memory management functions 1 The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation.[...]

所以我们不能认为环境在为你做释放的工作。 否则,它将被添加到最后一句:“或直到程序终止。”

换句话说: 不释放内存不仅仅是不好的做法。它生成不可移植且不符合C的代码。 至少可以被视为“正确的”,如果有以下情况:[…]],由environment支持。

但如果你根本就没有操作系统,那就没有人在为你做这项工作了 (我知道通常在嵌入式系统中不会分配和重新分配内存, 但在某些情况下,你可能想这么做。)

在普通的C语言中(OP被标记) 这只会产生错误的和不可移植的代码。

其他回答

===将来的校对和代码重用怎么办?= = =

如果你不编写释放对象的代码,那么你就将代码限制为只有当你可以依赖于进程关闭释放内存时才能安全使用……例如,小型一次性使用项目或“一次性”[1]项目)……你知道这个过程什么时候结束。

如果您确实编写了free()释放所有动态分配内存的代码,那么您就可以在未来验证代码,并让其他人在更大的项目中使用它。


[1]关于“一次性”项目。在“一次性”项目中使用的代码有一种不被丢弃的方法。接下来,十年过去了,你的“一次性”代码仍在使用)。

我听说过一个故事,说有个人写了一些代码,只是为了让他的硬件工作得更好。他说“只是一个爱好,不会有大的和专业的”。多年后,很多人都在使用他的“爱好”代码。

It depends on the OS environment the program is running in, as others have already noted, and for long running processes, freeing memory and avoiding even very slow leaks is important always. But if the operating system deals with stuff, as Unix has done for example since probably forever, then you don't need to free memory, nor close files (the kernel closes all open file descriptors when a process exits.) If your program allocates a lot of memory, it may even be beneficial to exit without "hesitation". I find that when I quit Firefox, it spends several !minutes ! paging in gigabytes of memory in many processes. I guess this is due to having to call destructors on C++ objects. This is actually terrible. Some might argue, that this is necessary to save state consistently, but in my opinion, long-running interactive programs like browsers, editors and design programs, just to mention a few, should ensure that any state information, preferences, open windows/pages, documents etc is frequently written to permanent storage, to avoid loss of work in case of a crash. Then this state-saving can be performed again quickly when the user elects to quit, and when completed, the processes should just exit immediately.

如果您正在使用已分配的内存,那么您没有做错任何事情。当你编写的函数(main以外的)分配内存而不释放它,并且没有使它对程序的其余部分可用时,这就会成为一个问题。然后您的程序继续运行分配给它的内存,但没有办法使用它。您的程序和其他正在运行的程序将被剥夺该内存。

编辑:说其他正在运行的程序被剥夺了该内存并不是100%准确。操作系统总是可以让他们使用它,代价是把你的程序交换到虚拟内存(</ hand招手>)。关键是,如果您的程序释放了它不使用的内存,那么虚拟内存交换就不太可能是必要的。

这段代码通常可以正常工作,但是要考虑代码重用的问题。

你可能写了一些没有释放分配内存的代码片段,它以这样一种方式运行,然后自动回收内存。似乎还好吧。

然后另一个人将您的代码片段复制到他的项目中,以每秒执行1000次的方式。这个人现在在他的程序中有一个巨大的内存泄漏。一般来说不是很好,对于服务器应用程序来说通常是致命的。

代码重用在企业中很常见。通常公司拥有其员工生产的所有代码,每个部门都可以重用公司拥有的任何代码。因此,通过编写这种“看起来很无辜”的代码,您可能会给其他人带来潜在的麻烦。这可能会让你被炒鱿鱼。

为这个进程分配的所有内存将被OS标记为未使用,然后重用,因为内存分配是由用户空间函数完成的。

想象OS是一个上帝,而记忆是创造一个过程世界的材料,上帝用一些材料创造了一个世界(或者说OS保留了一些内存并在其中创造了一个过程)。无论这个世界上的生物做了什么,不属于这个世界的物质都不会受到影响。在这个世界过期后,OS神,可以回收分配给这个世界的材料。

现代操作系统在释放用户空间内存方面可能有不同的细节,但这必须是操作系统的基本职责。