我正在用C编写一个通用链表(在 Kyle Loudon 的书之后), 但是当谈到免费它时,我得到了一个段错误。
用于列表定义的数据类型:
typedef struct list_elem_
{
void *data;
struct list_elem_ *next;
} list_elem;
typedef struct link_list_
{
int size;
int (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
list_elem *head;
list_elem *tail;
} link_list;
用于销毁来电者数据的函数:
void destroy_data(void *data)
{
if(data)
free(data);
return;
}
由函数指针传递的Destroy:
void list_init(link_list *list, void (*destroy)(void *data))
{
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;
return;
}
释放清单:
void list_destroy(link_list *list)
{
void* data;
while(list_size(list) > 0)
if(list_rem_next(list, NULL, (void**)&data) == 0 && list->destroy != NULL)
list->destroy(data);
memset(list,0,sizeof(link_list));
return;
}
segfault由destroy_data中的free触发。
==============编辑====================
删除列表元素
int list_rem_next(link_list *list, list_elem *element, void **data)
{
list_elem *OldElement;
if(list_size(list) ==0)
return -1;
/* Remove the head */
if(element == NULL)
{
*data = list->head->data;
OldElement = list->head;
list->head = list->head->next;
if(list_size(list) == 1)
list->tail = NULL;
/* Remove other than head */
} else {
if(element->next == NULL)
return -1;
*data = element->data;
OldElement = element->next;
element->next = element->next->next;
if(element->next == NULL)
list->tail = element;
}
free(OldElement);
list->size--;
return 0;
}
===================编辑2 ==========================
主要内部
link_list myList;
int i;
int *iptr;
char *chrPtr;
list_init(&myList, destroy_data);
for(i = 0; i < 4; i++)
{
iptr = malloc(sizeof(int));
*iptr = i;
list_ins_next(&myList, NULL, iptr);
}
chrPtr = malloc(sizeof("uno\0"));
chrPtr = "uno\0";
list_ins_next(&myList,NULL,chrPtr);
chrPtr = malloc(sizeof("stringa numero due\0"));
chrPtr = "stringa numero due\0";
list_ins_next(&myList,NULL,chrPtr);
chrPtr = NULL;
iptr = NULL;
getchar();
list_destroy(&myList);
答案 0 :(得分:1)
在main()
的代码中,您有:
chrPtr = malloc(sizeof("uno\0"));
chrPtr = "uno\0";
\0
?strcpy()
发生了什么?由于这种滥用行为,您将未分配的内存指针传递给free()
;实际上,您将指向字符串常量的指针传递给free()
。这是未定义的行为,很容易导致崩溃!
问题不在于您最初显示的代码中;它在其他代码中。这也是为什么MCVE(Minimal, Complete, Verifiable Example) - 又名{SSCCE Short, Self-Contained, Correct Example)mentioned由Greg Hewgill - 如此重要的原因。我们无法调试您未显示的代码 - 并且确定问题不在您显示的代码中是不必要的困难工作。
您可以使用:
chrPtr = strdup("uno"));
list_ins_next(&myList, NULL, chrPtr);
chrPtr = strdup("stringa numero due");
list_ins_next(&myList,NULL,chrPtr);
避免麻烦。如果做不到这一点,你可以使用:
chrPtr = malloc(sizeof("uno"));
strcpy(chrPtr, "uno");
list_ins_next(&myList, NULL, chrPtr);
chrPtr = malloc(sizeof("stringa numero due"));
strcpy(chrPtr, "stringa numero due");
list_ins_next(&myList,NULL,chrPtr);
这些都没有检查内存分配是否成功;这也应该在生产代码中完成,可以说是在学校作业中。
请注意sizeof("string literal")
计算空字节,因此长度正确。同样注意strlen("string literal")
不计算空字节 - 小心!
代码中可能还有其他问题;我没有证实一切都很干净。但是这部分将更清洁,更有可能正常工作。
未显示函数list_size()
和list_ins_next()
。大小可以猜到; list_ins_next()
并不那么容易。
我还观察到代码在列表中插入了4个整数,然后是2个字符串。没有办法知道事后插入的是什么。 main()
中的代码非常不通用。支持代码可以处理它 - 但异构列表很棘手;不要尝试它,直到你没有遇到这种问题。一个整数列表;精细。一个字符串列表;精细。一个整数和字符串列表 - 狡猾!