没有相应free
的malloc
是否总是会产生内存泄漏,或者是否存在不产生内存泄漏的情况?
这取决于如何定义"内存泄漏"。如果您将其定义为在程序退出时具有任何已分配存储持续时间的未完成对象,那么是的,这是一个泄漏。这就是像valgrind这样的工具所报告的。然而,它根本不是一个有用的定义。
我对内存泄漏的定义大致是,尽管有一个有限的工作集,但程序在其生命周期内的总内存消耗量会无限增加。例如,如果我的浏览器中最多打开10个选项卡,指向相同的10个站点,但内存使用量不断增加,这就是内存泄漏。另一方面,分配缓冲区将整个文件加载到内存中,加载文件,反向打印,然后在不释放内存的情况下退出的程序不存在内存泄漏。
一个特别重要的情况是,没有free
的malloc
不仅不是泄漏的,而且是绝对必要的(对于不能对其运行的整个程序进行假设的通用代码),即使用运行时分配的常量表,其生成由call_once
控制。无论您尝试释放这些表的时间有多晚,代码(在另一个线程或atexit
处理程序等中)都有可能在释放后尝试访问它,而call_once
类型的接口有意不提供任何同步任何访问的方法,除非是第一次调用(这是它们避免在每次读取时引入不必要的获取障碍/同步成本的方法)。
请注意,这里的"工作集"概念有点主观,而且承载力很强。通常情况下,内存泄漏是软件在用户不再考虑时仍在考虑其工作集的某个部分的问题
内存泄漏
是指程序分配内存,在不再使用时无法释放内存,并且无法跟踪其地址(malloc
、calloc
或realloc
返回的指针值)的情况。
由于指针丢失,内存将无法再释放,并将一直连接到程序,直到程序退出。
如果程序退出,则操作系统将回收与其相关的所有内存(除了本问题范围之外的罕见情况),因此内存泄漏不会产生任何后果。
如果程序执行时间很长,可能直到系统关闭,则程序上未使用的内存块不能用于其他目的。如果这样浪费的内存量很小,那么也不会产生任何后果。
相反,如果程序不断分配更多内存而不释放内存,则系统将耗尽可供程序使用的内存,并返回分配请求的NULL
,或者由于使用虚拟内存来满足请求而变得不稳定,这是以牺牲其他程序为代价的,也是以对存储设备进行漫长的交换操作或其他压缩技术为代价的。在某个时刻,系统可能会随机终止进程,以尝试恢复可用内存。
此类内存泄漏是有问题的,必须避免。它们在库函数中尤其有问题,这些函数可能用于为扩展会话运行的程序,如web浏览器、电子邮件阅读器、文件管理器、媒体播放器、程序管理器。。。
与其他编程语言不同,C没有嵌入式垃圾收集器,可以确定哪些已分配的内存块仍在使用,因此程序员有责任跟踪所有已分配的块并尽快释放它们。高级工具,如valgrind,可用于验证是否在程序退出时释放了所有分配的块。虽然没有必要在退出时释放内存,但这是一种很好的编程实践,也是确定是否已考虑所有分配的内存块的好方法。
答案可能取决于malloc
的实现,但通常有两种情况下malloc
不会产生内存泄漏:
-
当您将其0作为大小参数传递时,一些实现将只返回
NULL
而不分配任何内容,而另一些实现将返回唯一指针,即使这算作已分配的零字节,您也会在记账记录中泄漏大约64个字节。 -
当内存不足时。检查全局变量
errno
以获得特定值,通常为ENOMEM
以查看它是否失败。在这种情况下,malloc
也返回NULL
。
该标准根本不需要内存泄漏。因此,从本质上讲,没有任何情况可以保证内存泄漏。
另一方面,该标准也不要求在您提到的场景中不会发生内存泄漏。
在大多数情况下,当程序退出时,所有分配的内存都将被释放。但在某些系统上可能会有例外,尤其是嵌入式系统。如果这对你的程序至关重要,你不应该依赖它