我正在研究Zed Shaw的“学习艰难之路”,并对练习19(下面的描述和链接)提出了一个问题。
瘦子:在读取/输入代码时,让我感到震惊的是,在程序执行开始时,我们从未明确地释放了malloc在创建各种对象时的内存(下面会详细介绍)。 valgrind证实了这一点:valgrind报告在执行开始时分配了12个块(或608个字节);在程序终止时,这些块被报告为丢失(大多数是间接丢失,一些是直接丢失)。
那么......这段代码代表了良好(甚至可接受)的内存管理技术吗?或者缺少内存释放是一个错误?似乎是后者但是因为我是C n00b而想得到别人的意见。
(鉴于所有相关练习都没有涉及更改程序以确保我们释放malloc内存,我假设发布的代码是合理的,即代表良好的编码实践...)< / p>
我将概述下面的练习。我没有完整地重新发布代码,而是包含以下链接:http://c.learncodethehardway.org/book/ex19.html。
(Mods:对不起,如果链接到外部网站不是犹太人,请lmk,我会把它删除,我只是不想重现他的网站上发布的材料,因为潜在的版权问题。)
运动概述:
练习是制作一个简单的基于文本的RPG,用户可以在其中(i)选择从一个房间移动到另一个房间(即,从任何房间,你可以选择往北/南/东/西或一些其子集)和(ii)选择攻击一个怪物(谁在其中一个房间)。实施的快速摘要(侧重于相关部分)如下:
正如您所看到的,我们从不调用函数来释放Map,Monster和Room对象的内存(既不是'free'也不是'object_destroy'函数,我们在object.h / object.c中声明/定义) 。
注意:下面的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)
答案 0 :(得分:3)
这很糟糕,但在练习练习中很常见。通常,他们说它并不重要,因为OS会在进程死后释放所有内存。这是真的,但你不应该在生产代码中依赖于此。
所以我建议你尝试从一开始就编写一个好的代码并明确释放所有的内存块。
这完全不是关于效率,而是关于在设计应用程序时做出正确的决定。例如,在这个示例应用程序中,应该释放内存,在怪物死亡之后,房间应该破坏它们拥有的对象,并且地图应该破坏它的房间。这不仅仅是您编写的应用程序,只是在几次尝试后将其丢弃。它是一个库,应该被其他人使用。换句话说,这是玩具应用程序和真实生产代码之间的区别,可以在服务器24/7/365上使用。这就是一个优秀的程序员和一个猴子编码器之间的区别。
答案 1 :(得分:2)
与ivg says相反,在破坏船员开始之前,整齐地扫地并带出垃圾,放纵你的OCD是一个坏主意。
你会通过不必要的推迟来惹恼别人。
(显然,这只适用于破坏工作人员过时的工作,比如在具有功能性记忆保护的任何平台上释放记忆。此外,在编程练习中,扫除所有楼层有时是您应该尝试学习的事情之一。)
Raymond Chen关于该主题的博客文章:http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
来自Hans Boehm(Boehm GC)的a quote:分配误区4:非垃圾收集程序应该始终释放它们分配的所有内存。
真相:经常执行的代码中省略的解除分配会导致泄漏增加。它们很少被接受。但是在程序退出之前保留最多分配内存的程序通常执行得更好而没有任何干预重新分配。如果没有免费的话,Malloc会更容易实现。
在大多数情况下,在程序退出之前释放内存是没有意义的。操作系统无论如何都会收回它。免费将触及死亡对象中的页面;操作系统不会。
后果:小心使用&#34;检漏仪&#34;计算分配。一些&#34;泄漏&#34;很好!