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

时间:2017-10-28 16:40:49

标签: arrays struct vala

我正在尝试创建一个小的固定大小的字符串列表,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结构和结构数组的所有内容,但是那里的一点点也没有启发我。

固定大小的数组似乎用“空”结构进行初始化,我是否需要在某种程度上初始化它? 我对这里的结构数组有什么误解? 是否有另一种方法来实现固定大小的字符串,int元组列表?结构阵列是否不适合它?

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

1 个答案:

答案 0 :(得分:0)

首先,您可以通过特定的" 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)如何在{gpointer*之前投放到destroy_func ()在其上调用1}}。

如果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(数组中的struct的地址)上调用destroy函数(s_destroy aka S*)。

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

PS:使用动态数组工作正常,我会这样做或使用更高级别的数据类型,如Gee.ArrayList而不是静态数组。