简体   繁体   English

关于与free()一起使用时指针与数组表示法之间的区别

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM