我正在研究 C 语言中的动态数组列表。 当我尝试在释放后将一个元素重新添加到一个数组列表时,我遇到了一些问题。
结构:
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);
}
}
}
将元素插入数组列表:
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->
开头的三行。
如果您的帖子中没有包含最小的可编译可验证示例,这将仅限于一般建议:
一个潜在的问题是原型:
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
。
关于结构结构的一些注释:
创建将用于链表的结构时,通常像您所做的那样包含结构标记,但也包括结构的指针实例作为成员。 这你没有做过,但你应该考虑一下。
例如,考虑从下面修改您的原始结构:
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;