2009-10-28 168 views
0

你如何解决你从漏洞本身的函数返回的内存泄漏?当您返回泄漏的内存时修复内存泄漏?

例如,我做了一个char* returnMe = new char[24324]; returnMe是从函数返回的结果。你如何解释这种内存泄漏?一旦它被返回,你如何销毁它?我有一些内存管理规则,它会在内存泄漏上抛出运行时错误来阻止它,所以我无法真正忽略它。

Orrr我是一个傻瓜,这不是泄漏,意味着泄漏在别处?

+0

这只是一个泄漏,如果你没有参考它,因此没有是释放它。 – 2009-10-28 02:24:47

+0

尽管我的例子,它开始作为一个BYTE数组,并在返回时转换为char *,因为函数返回char *。这可能是原因吗? – Mark 2009-10-28 02:26:00

+0

@Shhnap:对你的评论精确:如果你从堆栈中引用它。如果两个元素互相引用,但无法从堆栈访问,则会泄露... – 2009-10-28 07:25:59

回答

13

这不是一个泄漏,如果你回吧(当然,这不是你的泄漏)。

您需要考虑资源所有权。如果你从你的函数返回一个分配的缓冲区,函数的调用者现在负责它。 API应该明确说明它在完成时需要被释放。

无论他们自己释放它还是将它传递给另一个函数以释放它(封装以防止释放内存需要做更多工作)是API的另一个问题。

3

指针returnMe仍然可以返回delete[]。这不是内存泄漏,除非您忘记删除returnMe

+0

嗯......这就是delete [] returnMe。删除returnMe通常会工作,但实际上并不正确。 – 2009-10-28 02:32:42

+0

对 - 谢谢。改变它删除[] – 2009-10-28 02:33:47

2

如果你的函数返回一个已分配的缓冲区,那么就没有泄漏。更好的是,如果客户代码有意识地调用你的例程并且对返回的内容没有做任何事情,那么会出现泄漏,但在这种情况下,这是客户端代码违反了你的合同。

当缓冲区返回时,它由客户端代码控制。一般来说,让可靠编程让分配/释放在同一层发生是一个好主意。这意味着如果你有一个返回缓冲区的例程,你应该有一个相应的例程来释放它,即使客户端代码可以调用delete []。

例如:假设你有这样的代码

char *mylib_gimmeh_buffer() { 
    char* returnMe = new char[24324]; 
    return returnMe; 
} 

为了对称,你应该也

char *mylib_free_buffer(buffer) { 
    delete[] buffer; 
} 

现在,您的客户端代码应该这样的表现

buf = mylib_gimmeh_buffer(); 
/* do something with buf */ 
mylib_free_buffer(buf); 

如果您客户端做这样的事情

mylib_gimmeh_buffer(); // just for fun 

或类似这样的

buf = mylib_gimmeh_buffer(); 
/* do something with buf */ 
/* never call mylib_free_buffer() */ 

然后有内存泄露

1
char* function() 
{ 
    char* returnMe = new char[24324]; 
    return returnMe; 
} 

int main() 
{ 
    char* pGetReturnME = function(); 
    delete [] pGetReturnME; 
} 

您仍然可以释放只有当你有一个指向分配内存的函数分配的内存。如果函数返回指向已分配内存的指针,则可以使用deletedelete[]进行释放。

为了避免多重删除或内存泄漏,您必须小心使用明确的内存分配和释放协议。

+0

请不要'void main()'。请参阅http://www.research.att.com/~bs/bs_faq2.html#void-main – 2009-10-28 02:30:58

+0

谢谢。固定相同。 – 2009-10-28 02:33:21

1

调用函数负责释放返回的内存。

void function() { 
    char *to_free = NULL; 
    //to_free does not need to be freed yet 

    to_free = function_that_uses_new_to_set_return(); 

    //to_free now must be freed if that function worked 
    if (to_free != NULL) delete[] to_free; 
} 
+0

你当然不想在已经用new分配的指针上调用'free'。你应该编辑这个帖子来将'free'改为'delete []' – 2009-10-28 02:35:11

1

尽管可能有一个分配内存并返回指针的函数,但它确实很容易出错......每当有人调用该函数时,他们都需要知道函数将为其分配内存,并且他们需要知道他们有责任释放该内存,并且他们需要知道在完成内存释放时使用的适当方式(delete?delete []?free()?还有其他内容?),以及他们需要确保在任何情况下自由发生一次,并且他们需要确保在自由发生之后不再重新引用指针。

不可避免的是,在一个不平凡的程序中,某个人(可能是你!)会得到其中一个错误的东西。然后有人(可能是你)会花费几个小时的时间与调试器(或者如果你幸运的话,valgrind)追踪为什么你的程序有时会崩溃或泄漏内存。这真的没有什么乐趣。

幸运的是,在C++中,有更好的方法来解决这个问题,这对于调用者来说很难实现。例如,您可以返回一个shared_array,而不是返回一个原始指针,它会在最后一个指针消失时自动删除分配的内存。这样,没有人需要考虑内存管理,它“只是有效”。

一旦你习惯了这样做,你永远不会想回去!

0

一种解决方法是以难以泄漏的方式返回内存。例如。将其作为boost::shared_ptr用自定义删除器返回(因为您需要删除[])。现在它实际上需要调用者的努力来泄漏。