提出garray是否会删除它?

发布于 2025-02-10 19:30:52 字数 855 浏览 1 评论 0原文

#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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

意犹 2025-02-17 19:30:52
  • 为什么在transform_pointer_contents的末尾的unref引起双重?

据推测,garray对象本身都不是双重释放的,而是临时对象数据的动态空间(tmp-&gt; data)。那是因为

*arr = *tmp

执行浅副本。然后,当您减少临时的参考计数时,Glib会划分内部存储,arr-&gt; data仍然指向。当arr后来不参考时,Glib试图再次对该数据进行处理。

请注意,还遵循最初分配给arr元素的数据存储。

最重要的是,GLIB不支持通过结构分配复制garray。而是使用GLIB数组函数来操纵Garray s。

  • 我怀疑TMP的退化也没有[arr],如果是这样,它如何工作?

解开TMP不解开arr。但是,鉴于您对arr的不支持的操作,解开tmp具有与> arr关联的元素存储(然后)的副作用。

我认为C ++中类似的参考口类型可以通过覆盖解释操作员来起作用,但是C肯定不起作用?

取消运算符(*)与观察到的不当行为无关,与GLIB的参考计数无关。不要将“参考”在此处的“参考”的不同用途混为一谈。在任何情况下,C都没有操作员超载。

问题在于,您不当导致一个garray的内部状态被与另一个的内部状态相反,因此当Glib释放一个响应一个参考数数时,它会降至零,以下另一个被损坏。首先,并不是说混蛋是一个干净的情况。

  • 我是否可以保证没有UNREF?
  • 可以正确释放TMP

不,您可以安全地假设tmp 不是如果其参考计数未降低到零,则可以正确释放。因此,在丢失指针之前,请继续UNREF。如上所述,您需要更改的是结构分配。使用glib函数来操纵garray s。对于那些熟悉GLIB的人来说,可能会有可行的捷径,但是在这一点上,那不是您。

  • Why does the unref at the end of transform_pointer_contents cause a double-free?

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 because

*arr = *tmp

performs a shallow copy. When you then decrement the reference count of the temporary, GLib deallocates that internal storage, which arr->data still points to. When arr 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 GArrays via structure assignment. Instead, use GLib array functions to manipulate GArrays.

  • I suspect that the dereferencing of tmp also unrefs [arr] somehow, if that is true, how does it work?

unrefing tmp does not unref arr. But given your unsupported manipulation of arr, unrefing tmp has a side effect of deallocting the element storage (then) associated with arr.

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?

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.

  • Do I have a guarantee that tmp is properly freed without the unref?

No, you can pretty safely assume that tmp is not properly freed if its reference count is not reduced to zero. So do continue to unref 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 the GArrays. There may be viable shortcuts for people who understand GLib well, but at this point, that's not you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文