C:这段代码是如何释放malloc-ed空间的?

C:这段代码是如何释放malloc-ed空间的?,c,memory-management,C,Memory Management,我正在阅读Zed Shaw的《艰苦学习C》,对练习19(下面的描述和链接)有一个问题 skinny:在阅读/输入代码时,我突然意识到,在程序执行开始时创建各种对象(下面更详细)时,我们从未显式释放内存。valgrind确认:valgrind报告在执行开始时分配了12个块(或608字节);这些块在程序终止时报告为丢失(大部分是间接丢失的,一些是直接丢失的) 那么……这段代码代表了良好(甚至可以接受)的内存管理技术吗?还是内存释放不足是一个bug?似乎是后者,但由于我是一名C n00b,我想征求其他

我正在阅读Zed Shaw的《艰苦学习C》,对练习19(下面的描述和链接)有一个问题

skinny:在阅读/输入代码时,我突然意识到,在程序执行开始时创建各种对象(下面更详细)时,我们从未显式释放内存。valgrind确认:valgrind报告在执行开始时分配了12个块(或608字节);这些块在程序终止时报告为丢失(大部分是间接丢失的,一些是直接丢失的)

那么……这段代码代表了良好(甚至可以接受)的内存管理技术吗?还是内存释放不足是一个bug?似乎是后者,但由于我是一名C n00b,我想征求其他人的意见

(考虑到附带的练习都不涉及更改程序以确保释放malloc-ed内存,我假设发布的代码是合理的,即代表良好的编码实践…)

我将在下面概述这个练习。我没有完整地重新发布代码,而是添加了链接:

(很抱歉,如果链接到外部网站是不符合犹太教的,请lmk,我会把它取下来,因为潜在的版权问题,我只是不想复制他网站上发布的材料。)


演习概述:

这个练习是制作一个简单的基于文本的RPG,用户可以(i)选择从一个房间移动到另一个房间(即,从任何房间,你可以选择去北/南/东/西或其中的一些子集)和(ii)选择攻击一个怪物(在其中一个房间)。实施情况的简要总结(重点是相关部分)如下:

  • 我们定义了一个类型(+struct)“Object”(在Object.h和Object.c中) 链接页面上的文件),其中包括 函数)调用“malloc”和析构函数的构造函数 (可能不是技术术语)称之为“免费”
  • 在ex19.h文件中,我们继续定义以下内容 类型(+结构):地图、房间和怪物,每个都包括一个 “Object”(即我们在Object.h和Object.c中定义的对象)也是如此 就像其他东西一样
  • Gameflow在ex19.c文件中定义。我们就是在这个文件里找到的 创建地图、怪物和几个房间的实例
  • 如您所见,我们从未调用函数来释放地图、怪物和房间对象的内存(在Object.h/Object.c中声明/定义的“free”或“Object\u destroy”函数)


    注意:下面的Valgrind输出是我从站点复制粘贴的代码的结果;我确保不使用我重新键入的文件版本,以免引入错误

    Valgrind输出:

    ==10184== 
    ==10184== HEAP SUMMARY:
    ==10184==     in use at exit: 608 bytes in 12 blocks
    ==10184==   total heap usage: 12 allocs, 0 frees, 608 bytes allocated
    ==10184== 
    ==10184== 608 (64 direct, 544 indirect) bytes in 1 blocks are definitely lost in loss record 12 of 12
    ==10184==    at 0x4C2C934: calloc (vg_replace_malloc.c:623)
    ==10184==    by 0x400FCF: Object_new (object.c:52)
    ==10184==    by 0x400E53: main (ex19.c:206)
    ==10184== 
    ==10184== LEAK SUMMARY:
    ==10184==    definitely lost: 64 bytes in 1 blocks
    ==10184==    indirectly lost: 544 bytes in 11 blocks
    ==10184==      possibly lost: 0 bytes in 0 blocks
    ==10184==    still reachable: 0 bytes in 0 blocks
    ==10184==         suppressed: 0 bytes in 0 blocks
    ==10184== 
    ==10184== For counts of detected and suppressed errors, rerun with: -v
    ==10184== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    

    这是一个不好的练习,但在练习中很常见。通常,他们说这无关紧要,因为操作系统会在进程结束后释放所有内存。这是真的,但在生产代码中永远不应该依赖于此

    因此,我建议您从一开始就尝试编写一个好的代码,并显式释放所有内存块

    更新
    这不是关于效率,而是关于在设计应用程序时做出正确的描述。例如,在这个示例应用程序中,内存应该被释放,在怪物死后,房间应该销毁他们拥有的对象,而地图应该销毁房间。这不仅仅是您编写的一个应用程序,而是经过多次尝试后将其丢弃。这是一个图书馆,应该被其他人使用。换句话说,这就是玩具应用程序和真正的生产代码之间的区别,可以在服务器上24/7/365使用。这就是一个好的程序员和一个猴子程序员之间的区别。

    这是一个不好的,但在实践中很常见的练习。通常,他们说这无关紧要,因为操作系统会在进程结束后释放所有内存。这是真的,但在生产代码中永远不应该依赖于此

    因此,我建议您从一开始就尝试编写一个好的代码,并显式释放所有内存块

    更新 这不是关于效率,而是关于在设计应用程序时做出正确的描述。例如,在这个示例应用程序中,内存应该被释放,在怪物死后,房间应该销毁他们拥有的对象,而地图应该销毁房间。这不仅仅是您编写的一个应用程序,而是经过多次尝试后将其丢弃。这是一个图书馆,应该被其他人使用。换句话说,这就是玩具应用程序和真正的生产代码之间的区别,可以在服务器上24/7/365使用。这就是一个好的程序员和一个猴子程序员之间的区别。

    与此相反,在救援人员开始之前,整洁地清扫地板,把垃圾倒出来,纵情于你的工作是个坏主意

    你无谓地拖延别人,会使他们无休无止地烦恼

    (显然,这只适用于失事船员淘汰的工作,比如在任何具有功能性记忆保护的平台上释放内存。此外,在编程练习中,扫除所有楼层有时是你应该尝试学习的内容之一。)

    陈雷蒙(Raymond Chen)关于该主题的博文:

    来自Hans Boehm(Boehm GC):

    分配谬论4:非垃圾收集程序应该总是释放它们分配的所有内存

    真相:在频繁执行的代码中省略的释放会导致越来越多的泄漏。它们很少被接受。但在程序退出之前保留大部分已分配内存的程序通常在没有任何干预释放的情况下运行得更好。如果没有免费软件,Malloc更容易实现

    在大多数情况下,在程序退出之前释放内存是没有意义的。操作系统无论如何都会回收内存。自由意志在死物中触摸和翻页;操作系统