提出garray是否会删除它?
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <glib.h>
void transform_pointer_contents(GArray* const arr) {
GArray* const tmp = g_array_new(true, true, sizeof(uint8_t));
const uint8_t example_num = 5;
g_array_append_val(tmp, example_num);
*arr = *tmp
// Why does this cause a double-free error?
g_array_unref(tmp);
}
int main() {
GArray* const arr = g_array_new(true, true, sizeof(uint8_t));
transform_pointer_contents(arr);
printf("Arr length is %d/n", arr->len);
g_array_unref(arr);
}
问题
- 为什么在
transform_pointer_contents
的末尾的UNRE会导致双重免费? - 我怀疑
tmp
的放证也以某种方式取消了它,如果是真的,它如何工作?我认为,C ++中类似的参考口类型可以通过覆盖取消运算符来起作用,但是C肯定无法正常工作? - 我是否可以保证
tmp
在没有UNRE的情况下可以正确释放?
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <glib.h>
void transform_pointer_contents(GArray* const arr) {
GArray* const tmp = g_array_new(true, true, sizeof(uint8_t));
const uint8_t example_num = 5;
g_array_append_val(tmp, example_num);
*arr = *tmp
// Why does this cause a double-free error?
g_array_unref(tmp);
}
int main() {
GArray* const arr = g_array_new(true, true, sizeof(uint8_t));
transform_pointer_contents(arr);
printf("Arr length is %d/n", arr->len);
g_array_unref(arr);
}
Questions
- Why does the unref at the end of
transform_pointer_contents
cause a double-free? - I suspect that the dereferencing of
tmp
also unrefs it somehow, if that is true, how does it work? I think that a similar reference-counted type in C++ would work by overwriting the dereference operator, but surely C doesn't work that way? - Do I have a guarantee that
tmp
is properly freed without the unref?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
据推测,
garray
对象本身都不是双重释放的,而是临时对象数据的动态空间(tmp-&gt; data
)。那是因为执行浅副本。然后,当您减少临时的参考计数时,Glib会划分内部存储,
arr-&gt; data
仍然指向。当arr
后来不参考时,Glib试图再次对该数据进行处理。请注意,还遵循最初分配给
arr
元素的数据存储。最重要的是,GLIB不支持通过结构分配复制
garray
。而是使用GLIB数组函数来操纵Garray
s。解开
TMP
不解开arr
。但是,鉴于您对arr
的不支持的操作,解开tmp
具有与> arr
关联的元素存储(然后)的副作用。取消运算符(
*
)与观察到的不当行为无关,与GLIB的参考计数无关。不要将“参考”在此处的“参考”的不同用途混为一谈。在任何情况下,C都没有操作员超载。问题在于,您不当导致一个
garray的内部状态
被与另一个的内部状态相反,因此当Glib释放一个响应一个参考数数时,它会降至零,以下另一个被损坏。首先,并不是说混蛋是一个干净的情况。不,您可以安全地假设
tmp
是 不是如果其参考计数未降低到零,则可以正确释放。因此,在丢失指针之前,请继续UNREF
。如上所述,您需要更改的是结构分配。使用glib函数来操纵garray
s。对于那些熟悉GLIB的人来说,可能会有可行的捷径,但是在这一点上,那不是您。Presumably, it is not either of the
GArray
objects themselves that is doubly freed, but rather the dynamic space for the temporary object's data (tmp->data
). That would be becauseperforms a shallow copy. When you then decrement the reference count of the temporary, GLib deallocates that internal storage, which
arr->data
still points to. Whenarr
later becomes unreferenced, GLib tries to deallocate that data again.Note that it follows also that the data storage originally allocated for the elements of
arr
was leaked.The bottom line is that GLib does not support copying
GArray
s via structure assignment. Instead, use GLib array functions to manipulateGArray
s.unrefing
tmp
does not unrefarr
. But given your unsupported manipulation ofarr
, unrefingtmp
has a side effect of deallocting the element storage (then) associated witharr
.The dereference operator (
*
) has nothing directly to do with the observed misbehavior, and absolutely nothing to do with GLib's reference counting. Do not conflate the distinct uses of "reference" in play here. And C does not in any case have operator overloading.The problem is that you have improperly caused the internal state of one
GArray
to be aliased to the internal state of another, so that when GLib frees one in response to its reference count dropping to zero, the internal state of the other is corrupted. Not that the aliasing was ever a clean situation in the first place.No, you can pretty safely assume that
tmp
is not properly freed if its reference count is not reduced to zero. So do continue tounref
it before you lose the pointer to it. What you need to change is the structure assignment, as described above. Use GLib functions to manipulate theGArray
s. There may be viable shortcuts for people who understand GLib well, but at this point, that's not you.