固定大小的结构数组的内存问题

Memory issues with fixed sized array of structs

我正在尝试创建一个小的固定大小的字符串列表,int 元组。固定大小的结构数组似乎是可行的方法,但是在操作数组条目时,我经常 运行 进入内存错误。到目前为止我尝试了什么:

public struct S {
    public string a;
    public int b;

    public S (string a, int b) {
        this.a = a;
        this.b = b;
    }
}

public class Test {
    public S arr[5];

    public static void main () {
        var test = new Test ();
        test.arr[0].a = "hi";
        test.arr[0].b = 5;
        /*   alternatively:   */
        //test.arr[0] = S ("hi", 5);
    }
}

我看过编译后的C代码,但我对C不是很熟悉。 我阅读了我发现的有关 vala 结构和结构数组的所有内容,但那里的一点点也没有启发我。

固定大小的数组似乎是用 "empty" 结构初始化的,我是否需要以某种方式对其进行初始化? 我对这里的结构数组有什么误解? 有没有另一种方法来实现固定大小的字符串列表,int 元组?结构数组不适合吗?

非常感谢任何帮助!这似乎是一项如此简单的任务,但我已经为此苦苦挣扎了好几天:/ ...

首先,您可以通过在 class 上指定 "Compact" 并禁用结构上的类型来简化 C 代码:

[CCode(has_type_id = false)]
public struct S {
    public string a;
    public int b;

    public S (string a, int b) {
        this.a = a;
        this.b = b;
    }
}

[Compact]
public class Test {
    public S arr[5];

    public static void main () {
        var test = new Test ();
        test.arr[0].a = "hi";
        test.arr[0].b = 5;
        /*   alternatively:   */
        //test.arr[0] = S ("hi", 5);
    }
}

不是完整的答案,但编译器生成的破坏代码似乎有问题:

void test_free (Test* self) {
    _vala_array_destroy (self->arr, 5, (GDestroyNotify) s_destroy);
    g_slice_free (Test, self);
}


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]);
            }
        }
    }
}

请注意 array 参数(属于 gpointer 类型,但从 S[] 转换而来,即 arr)如何在destroy_func () 被调用。

如果 arr 是一个动态数组就好了,但它不是。

如果我手动修改编译器输出,一切正常:

static void _vala_array_destroy (S* 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 (&array[i] != NULL) {
                destroy_func (&array[i]);
            }
        }
    }
}

销毁函数(destroy_func 又名 s_destroy)现在在有效的 S*(数组中结构的地址)上调用。

所以在我看来,您发现了一个编译器错误。

PS:使用动态数组效果很好,我要么这样做,要么使用一些更高级别的数据类型,如 Gee.ArrayList 而不是静态数组。