我已经在一些硕士项目中使用了C,但从未用它构建过生产软件。(.NET和Javascript是我的主业。)显然,在C语言中,free()内存的需求是至关重要的,如果你可以在一个例程中同时完成这两项工作,那就很好了。但是随着程序的增长和结构的加深,跟踪malloc'd在哪里以及什么适合免费变得越来越难。
我在互联网上四处寻找,只找到了一些关于这方面的通用建议。我怀疑的是,你们中的一些长期的C程序员已经想出了自己的模式和实践来简化这个过程,并将邪恶保持在你面前。
那么:您建议如何构建C程序结构,以防止动态分配成为内存泄漏?
发布于 2010-05-12 17:43:10
按合同进行设计。确保每个函数注释都清楚地说明了它的内存卫生-也就是说,它是否出错,释放分配的内容是谁的责任,以及它是否获得传入的任何东西的所有权。并与你的功能保持一致。
例如,您的头文件可能包含以下内容:
/* Sets up a new FooBar context with the given frobnication level.
* The new context will be allocated and stored in *rv;
* call destroy_foobar to clean it up.
* Returns 0 for success, or a negative errno value if something went wrong. */
int create_foobar(struct foobar** rv, int frobnication_level);
/* Tidies up and tears down a FooBar context. ctx will be zeroed and freed. */
void destroy_foobar(struct foobar* ctx);我由衷地赞同使用Valgrind的建议,它是一个非常棒的跟踪内存泄漏和无效内存访问的工具。如果您不是在Linux上运行,那么Electric Fence是一个类似的工具,尽管功能较差。
发布于 2010-05-12 18:59:51
大型项目通常使用“池”技术:在这种情况下,每个分配都与一个池相关联,并在池被释放时自动释放。如果你可以用一个临时的池做一些复杂的处理,这真的很方便,当你完成的时候,它可以一下子释放出来。子池通常是可能的;您通常会看到这样的模式:
void process_all_items(void *items, int num_items, pool *p)
{
pool *sp = allocate_subpool(p);
int i;
for (i = 0; i < num_items; i++)
{
// perform lots of work using sp
clear_pool(sp); /* Clear the subpool for each iteration */
}
}它使用字符串操作使事情变得容易得多。字符串函数将接受一个池参数,它们将在其中分配其返回值,该返回值也将是返回值。
缺点是:
发布于 2010-05-12 17:35:57
这不会是万无一失的(但这可能是C语言所期望的),而且可能很难使用大量现有代码,但如果您清楚地记录代码,并始终准确地说明谁拥有分配的内存以及谁负责释放它(以及使用什么分配器/释放分配器),这将有所帮助。此外,不要害怕使用goto为非平凡的资源分配功能强制使用单一入口/单一出口习惯用法。
https://stackoverflow.com/questions/2816940
复制相似问题