我在函数中创建drvm *drv结构。此结构本身包含包含malloc()-ed字段(uint32_t *buffer)的字段。这样做的代码类似于:

...
size_t elm_size = sizeof(model*);
uint32_t length = *(uint32_t*)len;

GArray *models = g_array_sized_new(FALSE, FALSE, elm_size, length);

model *mod;
for (int i = 0; i < length; ++i) {
    mod = create_model(...);
    g_array_append_val(models, mod);
}

这段代码不包含错误,经过高度测试。
在程序开始时,我注册函数free_all()(byatexit()),当执行exit()时,该函数应清除所有资源(尤其是内存)。
在这个函数中,我试图释放elements of GArray*model *结构)的内存和GArray *本身的内存:
GArray *models;
g_array_set_clear_func(models, clean_model);
if(!g_array_free(models, FALSE)) { //OK }

问题是当clean_model(void *data)glib库中调用时,我建议它包含指向一个model *元素的指针。但是地址不对,它似乎没有指向任何正确的值。既不GArray*,也不model*
而且GArray *models函数中的free_all()是正确的(与我创建它时相同),并且当我通过
for (int i = 0; i < len; ++i) {
    mod = g_array_index(models, model*, i); // Here I get correct pointer to model*
    clean_model(mod);
}

我得到了期望值。
问题:怎么了?如果GArray *的元素包含free_all()内存,我应该如何释放这些元素的内存?
标题部分:
struct _info {
    uint32_t *buffer;
    uint32_t len;
};

typedef struct _info info;

struct _prod {
    uint32_t *buffer;
    uint32_t len;
};

typedef struct _prod prod;

struct _model {
    uint32_t name;
    prod product;
    info inform;
};

typedef struct _model model;

struct _drvm {
    GArray *models;
    GArray *strings;
};

typedef struct _drvm drvm;

最佳答案

基本上,问题是您的clean_model函数被传递到model**而不是您期望的model*
记住GArray是用来存储完整的结构,而不仅仅是指向结构的指针。为了做到这一点,它需要将结构的全部内容复制到内部data数组中,因此指向结构的任何后续指针(传递给clean_model)都将指向data中的某个位置(即clean_model((elt_type*)&models->data[index * sizeof(elt_type)])-在您的情况下elt_typemodel*
为了解决这种情况,我们想到了两种选择,按照(主观)偏好的顺序:
使用GPtrArray代替;考虑到您的元素已经被动态分配了,内存管理/指针处理/类型转换(或者缺少)就不会那么混乱了
clean_model参数更改为model**
使用GArray来存储model结构而不是指针,但只有在可以将分配与填充模型内容(例如g_array_new(FALSE, FALSE, sizeof(model))fill_model(&g_array_index(models, model, i))分开)分开时才有意义。
在所有情况下,您可能还应该将TRUE传递给g_array_free,因为您似乎没有在随后的任何事情中使用GArray.data(这并不是说,如果您释放了其中所有有用的数据,那么这将没有任何意义)。

关于c - GArray元素的可用内存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14684739/

10-11 15:32