【问题标题】:Intricacies of malloc and freemalloc 和 free 的复杂性
【发布时间】:2012-05-05 21:03:13
【问题描述】:

我有两个相关的问题,因此我在这个单线程中问他们。

Q1) 我如何确认我的操作系统是否在程序终止时自动清除未“释放”的内存(使用 malloc 分配)?我正在使用带有 gcc-4.5.2 的 32 位 Ubuntu 11.04

根据 Steven Summit here 的教程页面,“释放未使用的内存(malloc'ed)是个好主意,但这不是强制性的。当您的程序退出时,它已分配但未分配的任何内存freed 应该被自动释放。如果您的计算机只是因为您的程序忘记释放它而以某种方式“丢失”内存,则表明您的操作系统存在问题或缺陷 "

Q2) 假设 foo.c 分配了 B 字节内存。稍后, foo.c 释放这个 B 字节的内存位置并将其返回给操作系统。 现在我的问题是,在当前实例中,那些特定的 B 字节内存位置是否可以重新分配给 foo.c(由操作系统),或者这些 B 字节不能分配给 foo .c 直到其当前实例终止?

编辑:我建议所有阅读我的问题的人阅读类似问题的答案herehere。这两个答案都详细解释了 malloc() 和 free() 的交互和工作,而没有使用非常深奥的术语。要了解内核使用的内存管理工具(例如 brk()、mmap())和 C 编译器使用的内存管理工具(例如 malloc()、free())之间的区别,this 是必读的。

【问题讨论】:

    标签: c memory-leaks malloc free ubuntu-11.04


    【解决方案1】:

    Q1) 我不确定您如何确认。然而,关于第二段,总是释放你分配的任何内存被认为是一种很好的风格。在这里可以找到一个很好的解释:What REALLY happens when you don't free after malloc?

    Q2) 肯定;这些字节通常最先被重新分配(取决于 malloc 实现)。有关详细说明,请参阅:How do malloc() and free() work?

    【讨论】:

    • 第二个链接有一个非常惊人的答案。 (stackoverflow.com/a/1119334/842808)
    • 有一种观点认为在退出程序时不应该释放内存——争论的观点是这就像清理你要搬出的房子,那会被拆除——这完全是浪费的时间和精力。我不完全同意,但不能指责这个论点:)
    【解决方案2】:

    当进程通过终止信号结束时,例如SIGSEGV,或者通过_exit(2)系统调用(恰好在从main返回时也会调用),所有的进程资源都被内核释放。特别是,进程地址空间,包括堆内存(使用mmap(2)(或者可能是sbrk(2))系统调用(由malloc库函数使用)被释放。

    当然,free 库函数要么(通常)通过将来对 malloc 的进一步调用使释放的内存区域可重用,要么(有时,对于大内存区域)使用例如释放一些大内存块给内核。 munmap(2) 系统调用。

    要了解有关进程 1234 的内存映射的更多信息,请按顺序读取 /proc/1234/maps 伪文件(或从进程内部读取 /proc/self/maps)。 /proc 文件系统是向内核查询进程的首选方式。 (还有/proc/self/statm/proc/self/smaps等很多有趣的东西)。

    freemalloc 的详细行为取决于实现。您应该将malloc 视为获取堆内存的一种方式,而将free 视为一种方式来说明以前的malloc-ed 区域是无用的,系统(即标准C 库+内核)可以做任何事情想要。

    使用valgrind 查找内存泄漏错误。您也可以考虑使用Boehm's conservative garbage collector,即使用GC_malloc 而不是malloc,并且不必费心手动释放内存。

    【讨论】:

    • 感谢您的满意答复。我想只要程序 foo.c 正在运行, /proc/foo/ 目录就会存在。正确的?那么,在那种情况下,我怎样才能得到相应的地图文件呢?尽管我确实检查了一些正在运行的 pid(例如 chrome)的地图文件,但它向我抛出了一堆惊人的信息。我很惊讶。 :)
    • 我不确定是否理解您的问题(不要忘记可执行文件和进程不一样;给定程序有一个可执行文件,例如您的 shell 的 /bin/bash,但可以在几个过程)。 /proc/1234/ 仅在进程 1234 存在时才存在。 (它是一个伪文件,不在磁盘上,所以读起来很快)。在该进程内部,/proc/self/ 是它的符号链接。
    • 为 valgrind 和 Boehm 的链接点赞。
    【解决方案3】:

    第一季度。您只需假设操作系统运行正常。

    第二季度。没有理由不能将字节重新分配给 foo.c,这仅取决于内存分配例程的工作方式。

    【讨论】:

      【解决方案4】:

      大多数现代操作系统都会回收分配的内存,因此您不必担心。
      操作系统不知道您的应用程序/程序是否泄漏了内存,它只是在进程完成后回收分配给进程的内容。

      是的,释放的内存可以重复使用(如果需要),重复使用可以在同一个实例中进行。

      【讨论】:

      • 有什么实用的方法可以确认这一点,比如说我可以制作或可以直接使用的测试软件?
      • @Abhinav:幸运的是,不需要这种开销。您只需要参考目标操作系统的文档,它就应该记录行为。
      • @Abhinav,确认哪一部分?您无法在不检测操作系统的情况下确认操作系统正在回收进程内存,这将减慢其内存管理速度,并且您很难在具有统一页面缓存的现代操作系统中破译。关于进程内存复用,请看valgrind.org
      猜你喜欢
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 2021-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多