我正在研究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语言的初学者^^'
问题(至少是一个问题)是array_list_free释放了array_list_t
对象本身,而不仅仅是内部动态数组:
free(array);
如果这本身不是一个问题(如果该对象没有被动态分配),则继续使用该对象而不为其分配新空间并初始化该空间是一个问题 - 在该函数本身和之后功能返回。
说到初始化,一个初始化函数值得注意的是它缺少你出现的那些。也许你通过普通的初始化器或默认初始化初始化你的对象,或者你可能只是省略了这个函数,但要注意你不能依赖未初始化的对象。
这里的大问题:
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->
开头的三行。
如果您的帖子中没有包含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;