我在我的函数中创建了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()
(由atexit()
),它应该在执行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()
是正确的(与我创建时相同)以及当我遍历GArray *
中的所有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 *
内存,我应该如何释放malloc()-ed
元素的内存?
标题的一部分:
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;
答案 0 :(得分:4)
基本上问题是您的clean_model
函数已经过model**
而不是您期望的model*
。
请记住,GArray
旨在存储完整的结构,而不仅仅是指向结构的指针。为了做到这一点,它需要将结构的全部内容复制到内部data
数组中,因此任何后续指向结构的指针(传递给clean_model
)都是将指向data
内的某个位置(即clean_model((elt_type*)&models->data[index * sizeof(elt_type)])
- 在您的情况下elt_type
为model*
)
为了解决这种情况,按照(主观)偏好的顺序会想到夫妻选择:
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
(不是因为它有任何意义)无论如何,你正在释放其中的所有有用数据。)