将一个元素重新添加到动态数组列表中(从内存中删除后)

问题描述 投票:0回答:3

我正在研究c中的动态数组列表。当我在重新分配后尝试将一个元素重新添加到一个arraylist时,我遇到了一些问题。

结构:

typedef struct array_list{
    void** array;
    size_t size;
    size_t capacity;
}array_list_t;

自由数组方法:

void* array_list_free(array_list_t* array) {
    free(array->array);
    free(array);
    array->capacity = 0;
    array->size = 0;
    array->array = NULL;
}

分配和重新分配方法:

void array_list_check_and_realloc(array_list_t* array) {
    if(!(array->capacity > array->size)) {
        if(array->capacity == 0){
            //the problem is probably here
            array->capacity++;
            array->array = realloc(array->array, sizeof(void*) * array->capacity);
        }else{
            array->capacity *= 2;
            array->array = realloc(array->array, sizeof(void*) * array->capacity);
        }
    }
}

将元素插入到arraylist:

void* array_list_insert(array_list_t* array, void* element) {
    array_list_check_and_realloc(array);
    size_t i;
    for( i = array_list_size(array); i > 0; --i ) {
        array->array[i] = array->array[i-1];
    }
    array->array[i] = element;
    array->size += 1;
}

主要:

    array_list_insert(array,8);
    array_list_free(array);
    array_list_insert(array,8); // <--- Segmentation Fault

当我尝试运行程序时,终端没有任何错误,似乎工作正常。但是,当我尝试使用调试器时,我可以看到分段错误,我不知道为什么(我使用CLION IDE)抱歉,我是c语言的初学者^^'

c list dynamic malloc dynamic-memory-allocation
3个回答
1
投票

问题(至少是一个问题)是array_list_free释放了array_list_t对象本身,而不仅仅是内部动态数组:

    free(array);

如果这本身不是一个问题(如果该对象没有被动态分配),则继续使用该对象而不为其分配新空间并初始化该空间是一个问题 - 在该函数本身和之后功能返回。

说到初始化,一个初始化函数值得注意的是它缺少你出现的那些。也许你通过普通的初始化器或默认初始化初始化你的对象,或者你可能只是省略了这个函数,但要注意你不能依赖未初始化的对象。


1
投票

这里的大问题:

void* array_list_free(array_list_t* array) {
    free(array->array);
    free(array);   
    array->capacity = 0;  //<<< oups, array points nowhere here as it has been
    array->size = 0;      //    freed on the previous line....
    array->array = NULL;
}

从函数中删除以array->开头的三行。


1
投票

如果您的帖子中没有包含minimal compilable verifiable example,则仅限于一般性建议:

一个潜在的问题是原型:

void array_list_check_and_realloc(array_list_t* array);

需要更改以容纳指向需要给予内存的对象的指针:

void array_list_check_and_realloc(array_list_t **array) 

这种粗略的也会改变它的调用方式,以及该函数内部的代码。

关于命名的一些评论: 使用的结构包括成员名称array。以下原型还包括名为array的整个结构的参数实例:

void* array_list_free(array_list_t* array);
void array_list_check_and_realloc(array_list_t* array); 

虽然合法,但这令人困惑。

使用_t后缀来命名你的结构array_list_t也不推荐用于reasons explained here

关于struct构造的一些注释:

在创建将用于链表的结构时,通常包括结构标记,就像您所做的那样,但也包括结构的指针实例作为成员。你还没有这样做,但你应该考虑一下。

例如,考虑修改原始结构:

typedef struct array_list{
    void** array;
    size_t size;
    size_t capacity;
}array_list_t;

更像这样的东西:(包括从typedef名称中删除'_t'后缀。)

typedef struct array_list{
    size_t size;
    size_t capacity;
    struct array_list *array //this becomes new nodes of your list. 
}ListNode;
© www.soinside.com 2019 - 2024. All rights reserved.