当你 Debug 一门过气语言生成的代码里面产生的 memory leak 时会发生什么 (a.k.a. 不要修改 vala 返回的 strv 的 length)

(会被写成 blog 发出来。)

直接上一段代码。

var array = elements.to_array ();
array.length = -1;
return "(" + string.joinv (" ", array) + ")";

提问,这段代码有什么问题?

它会生成这样的代码。

_tmp32_ = gee_collection_to_array ((GeeCollection*) _tmp30_, &_tmp31_);
array = _tmp32_;
array_length1 = _tmp31_;
_array_size_ = array_length1;
array_length1 = -1;
_tmp33_ = array_length1;
_tmp34_ = array;
_tmp34__length1 = array_length1;
_tmp35_ = _vala_g_strjoinv (" ", _tmp34_, _tmp34__length1);
_tmp36_ = _tmp35_;
_tmp37_ = g_strconcat ("(", _tmp36_, NULL);
_tmp38_ = _tmp37_;
_tmp39_ = g_strconcat (_tmp38_, ")", NULL);
_tmp40_ = _tmp39_;
_g_free0 (_tmp38_);
_g_free0 (_tmp36_);
result = _tmp40_;
array = (_vala_array_free (array, array_length1, (GDestroyNotify) g_free), NULL);
_g_object_unref0 (elements);
_g_free0 (_base);
_g_free0 (_tmp0_);
return result;

那么你再猜猜?给你点提示。

static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) {
    if ((array != NULL) && (destroy_func != NULL)) {
        int i;
        for (i = 0; i < array_length; i = i + 1) {
            if (((gpointer*) array)[i] != NULL) {
                destroy_func (((gpointer*) array)[i]);
            }
        }
    }
}


static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
    _vala_array_destroy (array, array_length, destroy_func);
    g_free (array);
}

´_>` strv 是一个不能改变大小的 array ……那么你改了它的大小……free 它的函数没法正常工作……然后就会造成 leak ……

This entry was posted in Linux and tagged , . Bookmark the permalink.

One Response to 当你 Debug 一门过气语言生成的代码里面产生的 memory leak 时会发生什么 (a.k.a. 不要修改 vala 返回的 strv 的 length)

  1. Ueno says:
    Firefox 57.0 Fedora x64

    You can find more background on that here:
    https://bugzilla.gnome.org/show_bug.cgi?id=686451
    (Thanks for tracking it down anyway; handling arrays in Vala is a pain in the neck)

    [Reply]

Leave a Reply

Your email address will not be published. Required fields are marked *

Note: Commenter is allowed to use '@User+blank' to automatically notify your reply to other commenter. e.g, if ABC is one of commenter of this post, then write '@ABC '(exclude ') will automatically send your comment to ABC. Using '@all ' to notify all previous commenters. Be sure that the value of User should exactly match with commenter's name (case sensitive).