【问题标题】:Creating a duplicate linked list returns SIGSEGV创建重复链表返回 SIGSEGV
【发布时间】:2021-11-22 03:12:41
【问题描述】:

所以我正在尝试创建一个包含指向数据的 void 指针的链表的副本 定义是:

typedef struct SinglyLinkedListNode {
    void *data;
    struct SinglyLinkedListNode *next;
}SinglyLinkedListNode;

typedef struct SinglyLinkedList {
    int size;
    struct SinglyLinkedListNode *front;
}SinglyLinkedList;

我的克隆链表函数的灵感来自 How to clone a linked list with a head/tail implementation? 唯一的区别是,我的链表没有尾部实现。

这是我的实现

SinglyLinkedListNode *cloneList(SinglyLinkedList *list, SinglyLinkedListNode *head) {
    if(head == NULL)
        return NULL;
    SinglyLinkedListNode *result = (SinglyLinkedListNode *)malloc(sizeof(SinglyLinkedListNode));
    result->data = head->data;
    if(head->next)
        result->next = cloneList(list, head->next);
    return result;
}

SinglyLinkedList *cloneFullList(SinglyLinkedList *list) {
    if(list == NULL)
        return NULL;
    SinglyLinkedList *result = (SinglyLinkedList *)malloc(sizeof(SinglyLinkedList));
    result->size = list->size;
    if(list->front != NULL)
        list->front = cloneList(result, list->front);
    return result;
}

但是当试图访问这样的数据时

SinglyLinkedList *list1 =  (SinglyLinkedList *)malloc(sizeof(SinglyLinkedList));
list1 = cloneFullList(list); //where list is an already existing list which works correctly
SinglyLinkedListNode *curr1 = (SinglyLinkedListNode *)malloc(sizeof(SinglyLinkedListNode));
curr1 = list1->front;

尝试访问 curr1->data 返回一个 SEGMENTATION FAULT。但是当我尝试通过使curr1 = list->front 访问数据时,数据被正确访问。我克隆链接列表的函数的错误在哪里?

【问题讨论】:

  • 删除每个例程中的第二个if。始终设置指针。

标签: c algorithm pointers linked-list clone


【解决方案1】:

我认为您没有正确理解事物的运作方式…… malloc 为您的对象分配内存,但不初始化它。 list1 = cloneFullList(list); 这将指针分配给一个新的目标,但丢失了分配空间的跟踪,没有初始化它。

此外,您的 cloneList 不会在最后一个元素上设置 next 指针(当 next 为空时),因此它保持未初始化状态。 cloneFullList 也一样(你应该删除 if(list->front != NULL),因为 cloneList 已经处理了 NULL 的情况)。

【讨论】:

    【解决方案2】:

    这部分变量名有错误:

    if(list->front != NULL)
        list->front = cloneList(result, list->front);
        // in previous line you modify list not result.
        // so result->front contents is undefined
        // you also missed the else when list->front is null
    return result;
    

    在这两个函数中,您都可以使用 calloc 将 NULL 指针或 0 整数作为初始值

    【讨论】:

      【解决方案3】:

      几个问题:

      • 在您的主代码中,您为*list1 分配内存,但随后立即为list1 分配不同的值,从而泄漏分配的内存。

      • 您的代码与curr1 犯了类似的错误

      • 仅当条件为真时,这些函数才会对next(或front)进行赋值,但这些属性应该始终获得值。

      • 有一个分配给list->front,应该是result->front

      没问题,但是cloneList的第一个版本确实不需要第一个参数(列表)。你可以只用 node 参数来做。

      所以这里是更新的代码:

      // No need for the list as first argument:
      SinglyLinkedListNode *cloneList(SinglyLinkedListNode *head) {
          if(head == NULL)
              return NULL;
          SinglyLinkedListNode *result = (SinglyLinkedListNode *)malloc(sizeof(SinglyLinkedListNode));
          result->data = head->data;
          result->next = cloneList(head->next); // No condition here
          return result;
      }
      
      SinglyLinkedList *cloneFullList(SinglyLinkedList *list) {
          if(list == NULL)
              return NULL;
          SinglyLinkedList *result = (SinglyLinkedList *)malloc(sizeof(SinglyLinkedList));
          result->size = list->size;
          result->front = cloneList(list->front); // No condition here
          return result;
      }
      
      int main(void) {
          // ... code that creates `list` comes here ...
          // 
          // No calls to malloc here...
          SinglyLinkedList *list1 = cloneFullList(list);
          SinglyLinkedListNode *curr1 = list1->front;
          // ...
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-05
        • 2014-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-09
        相关资源
        最近更新 更多