并且,欢迎回到另一个神话般的剧集'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
。
答案 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)
相同。