关于与free()

时间:2015-08-14 20:49:50

标签: c arrays pointers free dynamic-memory-allocation

并且,欢迎回到另一个神话般的剧集'Puny Mortals Asking (可能) Dumb Questions'。

我写了一个使用动态内存分配的K&R's exercise 1-16解决方案。作为检查我的工作的一部分,我通过Valgrind运行我的代码。 Valgrind报告了一些内存泄漏,尽管我有一个1:1的malloc:free比率(令人费解)。经过多次摆弄和阅读GNU c lib manual Valgrind user manual之后,我终于来到了SO。我读过的帖子都没有解决我的问题,直到我注意到其他无关问题的一些解决方案,这些问题使用的表示法可能表示为以下等价:

*(dbl_ptr + i) == dbl_ptr[i]

其中dbl_ptr的类型为char**,而i的类型为int

在我自己的原始代码中,我一直尝试以下列方式free()双指针:

for( i = 0 ; i < count ; ++i ) {
   free( (dbl_ptr + i) );     //Valgrind complains about a leak right here
}

free( dbl_ptr );

但是当我用这些代码重新编译程序时:

for( i = 0 ; i < count ; ++i ) {
    free( dbl_ptr[i] );    //No more Valgrind complaints
}

free( dbl_ptr );

然后报告程序是内存安全的。为什么呢?

帮助我理解,仁慈和仁慈的StackOverlords!

CODA:

如果您想要深入了解此处发生的事情,我建议您阅读templatetypedef对此帖的回答。我不相信我可以在我自己的代码中更好地解释出错的地方。事实证明,我的错误是对free()如何解释参数的误解的组合,以及对C中数组语法背后的语义的基本无知。

快速而肮脏:dbl_ptr[i]隐式取消引用dbl_ptr + i

3 个答案:

答案 0 :(得分:3)

当你调用free时,参数应该是指向要释放的内存块前面的指针。

所以让我们假设你有一个double*的数组。那个数组看起来像这样:

  dbl_ptr ---> [ 0 ][ 1 ][ 2 ] ... [ k ]
                 |    |    |         |
                 v    v    v         v
                arr  arr  arr       arr

现在,假设您致电

free(dbl_ptr + i);

以图形方式,此处dbl_ptr + i点(让我们选择i = 1

  dbl_ptr + i --------+
                      |
                      v
  dbl_ptr ---> [ 0 ][ 1 ][ 2 ] ... [ k ]
                 |    |    |         |
                 v    v    v         v
                arr  arr  arr       arr

因此,free将此调用解释为您要从分配给dbl_ptr的内存块的中间解除分配内容,而不是dbl_ptr[i]指向的内存块。 。这是一个问题,因为你不能用指向内存块中间的指针调用free

另一方面,呼叫

free(*(dbl_ptr + i));

free(dbl_ptr[i]);

然后你实际上是要解除i所指向的数组的dbl_ptr元素所指向的内存,这就是你想要的。

答案 1 :(得分:1)

您忘记了

中的解除引用运算符
free( (dbl_ptr + i) );   

应该是

free( *(dbl_ptr + i) ); 

答案 2 :(得分:1)

free释放指针参数指向的内存。在正确的情况下,free(dbl_ptr[i]),您从数组中查找指针,然后释放它指向的内存。在不正确的情况下,free( (dbl_ptr + i)),传递给它的指针实际上是指向数组中某个位置的指针,指向指向要释放的内存的指针。

要查看差异的简便方法,请考虑i = 0的情况。正确的版权是free(dbl_ptr[0])。错误的版本为free(dbl_ptr+0),与free(dbl_ptr)相同。