免费的通用链表在C - segfault



我正在用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;
}

是由destroy_data中的free触发的。

============== EDIT ====================

删除列表元素

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"));
chrPtr = "uno";
list_ins_next(&myList,NULL,chrPtr);
chrPtr = malloc(sizeof("stringa numero due"));
chrPtr = "stringa numero due";
list_ins_next(&myList,NULL,chrPtr);
chrPtr = NULL;
iptr = NULL;
getchar();
list_destroy(&myList);

在你的代码从main()你有:

chrPtr = malloc(sizeof("uno"));
chrPtr = "uno";
  1. 当C自动在它后面加一个时,为什么显式的 ?
  2. 你会说"内存泄漏"吗?你分配内存;通过将字符串字面值的地址分配给同一个指针,您立即覆盖指向该分配内存的唯一指针。
  3. strcpy()怎么了?

由于这种滥用,您正在将未分配的内存指针传递给free();实际上,您正在将指向字符串常量的指针传递给free()。这是未定义的行为,很容易导致崩溃!

问题不在你一开始展示的代码中;它在另一个代码里。这也是Greg Hewgill提到的MCVE(最小、完整、可验证的例子)——又名SSCCE(简短、自包含、正确的例子)如此重要的原因。我们没有办法调试你没有显示的代码——而且确定问题不在你显示的代码中是不必要的辛苦工作。

你可以使用:

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()中的代码非常不通用。支持代码可以处理它——但是异构列表很棘手;在你没有遇到这种问题之前不要尝试。一个整数列表;很好。一个字符串列表;很好。一个由整数和字符串组成的列表——狡猾!

相关内容

  • 没有找到相关文章

最新更新