zsh: segmentation fault && runtime error: member access within null pointer of type 'struct ListNode' [solution.c]

zsh: segmentation fault && runtime error: member access within null pointer of type 'struct ListNode' [solution.c]

这是一个函数,return一个链表由两个链表的和组成。 例如, 链表 1 : 1, 2, 3 链表 2 :4, 9, 6 输出:5, 1, 0, 1

    struct ListNode {
    int val;
    struct ListNode *next;
};

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode *head;
    struct ListNode *temp = head;
    int sum = 0;
    int carry = 0;

    while (l1 || l2 || carry) {
        temp->next = malloc(sizeof(struct ListNode));
        int x = (l1->val ? l1->val : 0);
        int y = (l2->val ? l2->val : 0);
        sum = (x + y + carry) % 10;
        carry = (x + y + carry) / 10;
        temp->next->val = sum;
        l1 = (l1 ? l1->next : NULL);
        l2 = (l2 ? l2->next : NULL);
        temp->next->next = NULL;
        temp = temp->next;
    }
    return (head->next);
}

我不知道是什么原因导致错误。

+ 当我将 int sum 声明为

int sum = (l1 != NULL ? l1->val : 0) + (l2 != NULL ? l2->val : 0) + carry;

没问题。但是,如果我尝试不同的方式

    if (l1 != NULL) x = l1->val;
    if (l2 != NULL) y = l2->val;
    int sum = x + y + carry;

在某些情况下会导致超时错误。 我唯一能想到的是 int 数据类型可能不足以存储一些数字。然而导致超时的输入只是[9,9,9,9,9,9,9,9]和[9,9,9,9]链表,也就是9+9的情况。所以,我迷路了。

两期:

  • head 从未初始化,因此导致未定义的行为。由于您似乎想要一个虚拟节点(作为 pre-head 节点),您应该使用新分配的节点进行初始化。

  • xy 的表达式可能取消引用 NULL 指针。而不是检查 l1->val 你应该检查 l1.

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode *head malloc(sizeof(struct ListNode)); // Corrected
    struct ListNode *temp = head;
    int sum = 0;
    int carry = 0;

    while (l1 || l2 || carry) {
        temp->next = malloc(sizeof(struct ListNode));
        int x = l1 ? l1->val : 0; // Corrected
        int y = l2 ? l2->val : 0; // Corrected
        sum = (x + y + carry) % 10;
        carry = (x + y + carry) / 10;
        temp->next->val = sum;
        l1 = l1 ? l1->next : NULL;
        l2 = l2 ? l2->next : NULL;
        temp->next->next = NULL;
        temp = temp->next;
    }
    return head->next;
}

然后您可以将代码重组为:

  • 避免代码重复;
  • 使用更相关的变量名;
  • 通过NULL 比较明确
struct ListNode* Node(int value) {
    struct ListNode *newNode = malloc(sizeof(struct ListNode));
    newNode->val = value;
    newNode->next = NULL;
    return newNode;
}

struct ListNode* addTwoNumbers(struct ListNode *l1, struct ListNode *l2) {
    struct ListNode *preHead = Node(0);
    struct ListNode *tail = preHead;
    int carry = 0;

    while (l1 != NULL || l2 != NULL || carry) {
        int sum = (l1 != NULL ? l1->val : 0) + (l2 != NULL ? l2->val : 0) + carry;
        tail = tail->next = Node(sum % 10);
        carry = sum / 10;
        if (l1 != NULL) l1 = l1->next;
        if (l2 != NULL) l2 = l2->next;
    }
    return preHead->next;
}