在呼叫者或被呼叫者中释放内存?

时间:2011-10-12 11:26:19

标签: c++ memory-management memory-leaks

一个函数(Say“fun()”)分配内存并将指针返回给已分配的内存。 我应该如何确保释放此内存。我无法在函数“fun()”中立即释放它,因为它返回给调用者。 如果fun()是图书馆的一部分怎么办?释放记忆是谁的责任。 在fopen()的情况下,内存由fclose()释放。但在我的情况下,反复调用“fun()”。所以我不能等到最后释放记忆。

6 个答案:

答案 0 :(得分:5)

以下是在OP承认使用C ++之前发布的C的答案。在该语言中,按照其他人的建议使用RAII和智能指针。

如果函数返回已分配的内存,则调用者负责释放,这必须在函数文档中说明。

如果需要更多清理,则由free提供,或者在库的未来版本中可能需要进行此类清理,那么您应该提供清理功能(如stdio与{{} 1}})进行解除分配。如果你无法预测将来是否有必要进行额外的清理,那么假设它在某个时刻是个好主意。包裹fclose很便宜。

将其视为一种对称形式:如果客户端从库中获取资源(对象),那么它最终负责将其交还给库进行处理:

free

在foolib 1.0中,void use_the_foo_library() { Foo *f = make_foo(); if (f == NULL) ERROR(); foo_do_bar(f); foo_do_baz(f); foo_destroy(f); } 只是

foo_destroy

但在版本2.0中,它可能已经发展到

void foo_destroy(Foo *p)
{
    free(p);
}

等。此样式与opaque pointer设计模式一致。它还使您可以随时使用特殊用途的内存分配器(例如pool allocator)替换void foo_destroy(Foo *p) { fclose(p->logfile); free(p); } malloc,而无需更改任何客户端代码。

答案 1 :(得分:5)

如果它是C ++,则不要将原始指针返回到内存,而是返回智能指针。

例如:

std::shared_ptr<TypePointedTo> data = fun();

这样,当shared_ptr破坏时,它会自动为你释放内存。

或者,如果它是要返回的数组,请使用向量,这将自动为您释放内存:

std::vector<BYTE> data = fun();

阅读优秀的评论,std :: unique_ptr在许多场景中可能比std :: shared_ptr更好。

如果是C ...请看其他答案!

答案 2 :(得分:2)

C解决方案:

  

如果fun()是图书馆的一部分怎么办?

然后你的库api应该记录调用者释放内存需要的事实 您还应该为此提供免费功能,并要求库的用户调用它以释放分配。

编辑:

C ++解决方案:

由于您编辑过说您正在使用C ++,因此最好使用智能指针(std::tr1::shared_ptr)为您自动处理内存。

如果因某些原因无法使用智能指针使用std::vector也是一个不错的选择。

答案 3 :(得分:2)

在C ++中,您将返回一个智能指针,该指针清楚地指出(并强制执行)所有权已传输给调用者,并允许调用者选择如何处理它。它还提供异常安全性,如果异常(或只是早期函数返回)导致资源的唯一指针超出范围,则防止内存泄漏。

在C ++ 03中,std::auto_ptr是最好的选择;在C ++ 11中,不赞成使用std::unique_ptr

答案 4 :(得分:0)

如果你需要在被叫者之外的内存,很明显它负责释放内存,因为你无法在被叫方中真正释放它。它与newdelete相同 - 你必须记住释放那个记忆。确保记录调用者负责内存管理的事实。

答案 5 :(得分:0)

您必须记录已分配内存并且调用者负责释放内存。你不能自己解放,因为你无法知道来电者的意图。在使用之前你会释放它。

你可以提供一个cleanUp()方法来调用并刷新内存,但是仍然依赖于调用者,你会在应该调用它时添加复杂性。

唯一真正的替代方案是建立一个聪明的“引用计数”机制,例如在Objective-C中(参见发布和自动释放)。