通过复制返回结构,封装指针

时间:2013-01-22 06:25:17

标签: c memory-management memory-leaks heap

假设我有以下内容:

typedef struct a_struct_s
{
     int* dynamic_pointer;
}
a_struct;

a_struct make_struct( int length )
{
     a_struct s;
     s.dynamic_pointer = calloc( sizeof( int ), length );
     // [check here to see if s.dynamic_pointer was allocated]

     return s;
}

由于make_struct()将返回结构s的副本,由它封装的指针是否会泄漏内存并且无法释放?此外,复制本身与动态分配s是否有性能成本?

4 个答案:

答案 0 :(得分:2)

没有。即使你复制了指针,它仍然指向同一个地方,所以你可以释放它。

答案 1 :(得分:2)

为什么会这样?指针不是分配的内存本身 - 如果你复制指针,它本身不分配内存。如果您稍后在其上调用free(),它将被正确释放。例如,这段代码不会泄漏内存:

a_struct s = make_struct(10);
free(s.dynamic_pointer);

答案 2 :(得分:1)

不,只要函数的调用者在结构指针成员上调用free(),它就不会泄漏内存。

记住规则:
当您拨打malloccalloc并且从不在同一地址呼叫free时,会发生内存泄漏。只要你这样做,就没有内存泄漏。

请注意,从函数返回动态分配的指针时,指定所有权语义非常重要。简而言之,您的接口应明确提到在函数调用之后,动态分配的指针成员由调用者拥有。

  

由于make_struct()将返回struct s的副本,由它封装的指针是否会泄漏内存并且无法释放?

是的,会返回结构的副本,但 shallow copy 基本上,这意味着返回的结构副本的指针成员指向与s的结构指针成员指向的内存位置相同的内存位置。 由于两个指针都指向同一个地址,只要调用者在返回结构的指针成员上调用free就没有泄漏。

  

副本本身是否会产生性能成本与动态分配s相比?

动态分配总是昂贵且更容易出错。尽量使用它们,除非你真的需要它们,否则不要使用它们。

答案 3 :(得分:1)

不,从你的角度来看它很好但是你可能想要考虑另一种分配方法,因为通过值返回一个带有指向内存块的指针的结构可能不那么明显,调用者需要释放其中的成员。

一种方法是使整个结构分配,然后有一个函数释放结构

a_struct* alloc_struct( int length )
{
     a_struct s = calloc( 1, sizeof(a_struct) );
     s->dynamic_pointer = calloc( sizeof( int ), length );
     return s;
}

void free_struct( a_struct *p )
{
    if ( p != NULL )
    { 
      free( p->dynamic_pointer );
      free(p);
    }
}