1

我在我的函数中创建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()(by 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 *modelsfree_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;
4

1 回答 1

4

基本上问题是你的clean_model函数被传递model**而不是model*你所期望的。

请记住,这GArray意味着存储完整的结构,而不仅仅是指向结构的指针。为了做到这一点,它需要将结构的全部内容复制到内部data数组中,因此任何后续指向结构的指针(传递给clean_model)都将指向内部的某个地方data(即clean_model((elt_type*)&models->data[index * sizeof(elt_type)])- 在你的情况下elt_type是哪里model*

为了解决这种情况,我想到了几个选项,按照(主观)偏好的顺序:

  1. 改为使用GPtrArray;鉴于您的元素已经动态分配,内存管理/指针处理/类型转换(或缺少)将不会那么混乱
  2. clean_model参数更改为model**
  3. 用于GArray存储model结构而不是指针,但只有当您可以将分配与填充模型内容分开时才有意义,例如g_array_new(FALSE, FALSE, sizeof(model))fill_model(&g_array_index(models, model, i))

在所有情况下,你也应该传递TRUE给,g_array_free因为你似乎没有在GArray.data之后使用任何东西(这并不是说无论如何你都在释放所有有用的数据。)

于 2013-05-14T23:54:19.033 回答