C中的Arraylist无法正常工作

我目前正在编写一个程序来实现C语言中的arraylist(或动态数组)…我认为我已经完成了70-80%,但是,我发现我的代码在测试时遇到了严重的问题。机器

简而言之,我将一组字符串(char *)插入到我的arraylist中,并试图在操作几次后显示它们。 但是,这就是我得到的:

CHECK: 1 CHECK: 2 CHECK: ܗ¿èۗ¿ CHECK: EàEàHAÿE؉Ⱥ CHECK: 5 CHECK: 6 

不幸的是,即使我已经两次检查了我的代码,我仍然无法弄清楚代码中的问题所在。

arraylist.h

 #ifndef _ARRAYLIST_H #define _ARRAYLIST_H #include  typedef char* value_type; struct arraylist { int size; value_type* data; }; extern void arraylist_initial(struct arraylist *list); extern int arraylist_get_size(const struct arraylist list); extern value_type* arraylist_get_data_collection(const struct arraylist list); extern void arraylist_set_data_collection(struct arraylist *list, value_type* data); extern void arraylist_add(struct arraylist *list, value_type value); extern value_type arraylist_get(const struct arraylist list, int index); extern int arraylist_indexof(const struct arraylist list, value_type value); #endif 

arraylist.c

 #include "arraylist.h" void arraylist_initial(struct arraylist *list) { list->size = 0; list->data = NULL; } int arraylist_get_size(const struct arraylist list) { return list.size; } value_type* arraylist_get_data_collection(const struct arraylist list) { return list.data; } void arraylist_set_data_collection(struct arraylist *list, value_type* data) { list->data = data; } void arraylist_add(struct arraylist *list, value_type value) { int size = arraylist_get_size(*list); value_type new_data[size + 1]; int index = 0; for(; index != size; ++index) { new_data[index] = arraylist_get(*list, index); } new_data[index] = value; arraylist_set_data_collection(list, new_data); ++list->size; } value_type arraylist_get(const struct arraylist list, int index) { if(index < arraylist_get_size(list)) { return list.data[index]; } else { return NULL; } } int arraylist_indexof(const struct arraylist list, value_type value) { int index = 0; for(; index != arraylist_get_size(list); ++index) { if(strcmp(list.data[index], value) == 0) { return index; } } return -1; } int main(void){ struct arraylist list; arraylist_initial(&list); arraylist_add(&list, "1"); arraylist_add(&list, "2"); arraylist_add(&list, "3"); arraylist_add(&list, "4"); arraylist_add(&list, "5"); arraylist_add(&list, "6"); int index = 0; for(; index != 6; ++index) { printf("CHECK: %s\n", arraylist_get(list, index)); } return 0; } 

正如其他人所说,问题出在arraylist_add()函数中,它需要动态分配内存。 这个问题实际上非常适合realloc() ,它将扩展动态分配的数组(意味着你不必进行复制循环):

 void arraylist_add(struct arraylist *list, value_type value) { int size = arraylist_get_size(*list); value_type *new_data; new_data = realloc(list->data, (size + 1) * sizeof new_data[0]); if (new_data) { new_data[size] = value; arraylist_set_data_collection(list, new_data); ++list->size; } } 

这甚至可以用于第一次分配,因为如果你传递一个NULLrealloc()工作方式就像malloc()

PS:

为了提高实现效率,您不应每次将数组扩展一个条目 – 而是与条目数分开跟踪已分配块的数量。

arraylist_add方法中,您将局部变量new_data的地址存储到列表中。 一旦控件退出该function,该变量将被销毁。 因此,当derefrenced调用未定义的行为时,您会有无效的指针。 要解决此问题,您需要使用malloc为堆中的字符串分配内存,即您需要执行类似value_type* new_data = (value_type*)malloc( (size + 1) * sizeof(value_type)); 。 还记得你必须自己使用free释放这个内存。

乍一看:在arraylist_add中,您将new_data声明为局部变量。 当您将其传递给arraylist_set_data_collection时,它会将指针传递给此数据。 但是,一旦arraylist_add返回main,new_data就会超出范围,因此不再有效。

考虑使用malloc和free手动执行深层复制和处理内存。

问题的根源在于:

 void arraylist_add(struct arraylist *list, value_type value) { int size = arraylist_get_size(*list); value_type new_data[size + 1]; ... arraylist_set_data_collection(list, new_data); ... ++list->size; } 

new_data在堆栈上声明。 在调用返回后使用该内存不再安全。 您需要使用malloc为数据分配空间,例如