[英]On the difference between pointer and array notation when used with free()
And, welcome back to another fabulous episode of 'Puny Mortals Asking
(Potentially)
Dumb Questions'. 并且,欢迎回到另一个有趣的小故事,“有趣的小矮人问
(可能)
愚蠢的问题”。
I wrote a solution to K&R's exercise 1-16 that uses dynamic memory allocation. 我为K&R的练习1-16使用动态内存分配编写了一个解决方案。 As part of checking my work, I ran my code through Valgrind. 作为检查工作的一部分,我通过Valgrind运行了代码。 Valgrind reported some memory leaks, though I had a 1:1 malloc:free ratio (which is perplexing). Valgrind报告了一些内存泄漏,尽管我的1:1 malloc:free比率(令人困惑)。 After much fiddling and reading of the GNU c lib manual and the Valgrind user manual , I eventually came to SO. 经过大量的摆弄和阅读GNU c lib手册 和 Valgrind用户手册 ,我最终来到SO。 None of the posts that I read really solved my problem, until I noticed some solutions to other unrelated problems that used a notation that may be expressed as the following equivalence: 我读过的所有帖子都没有真正解决我的问题,直到我注意到一些其他无关问题的解决方案,这些解决方案使用一种表示法可以表示为以下等价形式:
*(dbl_ptr + i) == dbl_ptr[i]
Where dbl_ptr
is of type char**
and i
is of type int
. 其中dbl_ptr
的类型为char**
而i
的类型为int
。
In my own, original code, I had been attempting to free()
a double pointer in the following manner: 在我自己的原始代码中,我一直试图通过以下方式free()
一个双指针:
for( i = 0 ; i < count ; ++i ) {
free( (dbl_ptr + i) ); //Valgrind complains about a leak right here
}
free( dbl_ptr );
But when I recompile the program with these lines instead: 但是当我用这些行重新编译程序时:
for( i = 0 ; i < count ; ++i ) {
free( dbl_ptr[i] ); //No more Valgrind complaints
}
free( dbl_ptr );
The program is then reported as being memory safe. 然后该程序被报告为内存安全。 Why? 为什么?
Help me to understand, merciful and benevolent StackOverlords! 帮助我理解,仁慈和仁慈的StackOverlords!
CODA: 结尾:
I recommend reading templatetypedef's answer to this post if you want a solid understanding of what happened here. 如果您想对这里发生的事情有深入的了解,我建议阅读templatetypedef对这篇文章的回答。 I don't believe I can write a better explanation of what was going wrong within my own code. 我不相信我可以在自己的代码中写出关于错误原因的更好的解释。 It turns out that my error was a combination of misunderstandings about how free()
interprets arguments, as well as a fundamental ignorance of the semantics behind the array syntax in C. 事实证明,我的错误是关于free()
如何解释参数的误解,以及对C语言中数组语法背后的语义的根本无知。
Fast and dirty: dbl_ptr[i]
implicitly dereferences dbl_ptr + i
. 快速又肮脏: dbl_ptr[i]
隐式取消引用dbl_ptr + i
。
When you call free
, the argument should be a pointer to the front of the block of memory you want to deallocate. 调用free
,参数应为指向要取消分配的内存块前端的指针。
So let's suppose you have an array of double*
s. 因此,假设您有一个double*
数组。 That array looks like this: 该数组如下所示:
dbl_ptr ---> [ 0 ][ 1 ][ 2 ] ... [ k ]
| | | |
v v v v
arr arr arr arr
Now, suppose you call 现在,假设您打电话
free(dbl_ptr + i);
Graphically, dbl_ptr + i
points here (let's pick i = 1
) 以图形方式, dbl_ptr + i
指向此处(让我们选择i = 1
)
dbl_ptr + i --------+
|
v
dbl_ptr ---> [ 0 ][ 1 ][ 2 ] ... [ k ]
| | | |
v v v v
arr arr arr arr
Therefore, free
interprets this call as if you want to deallocate something from the middle of the block of memory allocated to dbl_ptr
, rather than the block of memory pointed at by dbl_ptr[i]
. 因此, free
将此调用解释为您要从分配给dbl_ptr
的内存块的中间而不是从dbl_ptr[i]
指向的内存块中释放某些内容。 That's a problem, because you can't call free
with a pointer to the middle of a block of memory. 这是一个问题,因为您不能使用指向内存块中间的指针来进行free
调用。
On the other hand, calling 另一方面,打电话
free(*(dbl_ptr + i));
or 要么
free(dbl_ptr[i]);
then you're actually saying to deallocate the memory pointed at by the i
th element of the array pointed at by dbl_ptr
, which is what you want. 那么您实际上是在说要释放由dbl_ptr
指向的数组的第i
个元素所指向的dbl_ptr
。
You forgot dereference operator in 您忘记了在
free( (dbl_ptr + i) );
It should be 它应该是
free( *(dbl_ptr + i) );
free
deallocates the memory pointed to by the pointer argument. free
释放由指针参数指向的内存。 In the correct case, free(dbl_ptr[i])
, you look up a pointer from within the array, and then free the memory that it points at. 在正确的情况下, free(dbl_ptr[i])
会从数组中查找指针,然后释放其指向的内存。 In the incorrect case, free( (dbl_ptr + i))
, the pointer passed to it is actually a pointer to a location within the array, a pointer to the pointer to the memory you want to free. 在不正确的情况下, free( (dbl_ptr + i))
传递给它的指针实际上是指向数组中某个位置的指针,指向您要释放的内存的指针。
For an easy way to view the difference, consider the i=0 case. 为了轻松查看差异,请考虑i = 0的情况。 the correct verison is free(dbl_ptr[0])
. 正确的版本是free(dbl_ptr[0])
。 The incorrect version is free(dbl_ptr+0)
, which is the same as free(dbl_ptr)
. 不正确的版本是free(dbl_ptr+0)
,与free(dbl_ptr)
相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.