You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言链表insertAtEnd函数触发Segmentation Fault,求错误原因及解决

链表尾部插入函数触发Segmentation Fault的原因及修复

问题描述

正在学习链表插入操作,已实现insertAtBegin(在链表头部插入新节点)、insertAtIndex(在指定索引位置插入新节点)等函数。编写的insertAtEnd函数在运行时触发Segmentation Fault(段错误),注释掉该函数调用则无报错。完整代码如下:

#include <stdio.h>
#include <stdlib.h>

struct Node
{
    int value;
    struct Node *nextPtr;
};

void printValue(struct Node *ptr)
{
    while (ptr != NULL)
    {
        printf("%d\n", ptr->value);
        ptr = ptr->nextPtr;
    }
}

struct Node* insertAtBegin(struct Node* head, int value)
{
    struct Node *new;
    new=(struct Node *)malloc(sizeof(struct Node));
    new->nextPtr=head;
    new->value=value;
    return new;
}

void insertAtIndex(struct Node* head, int index, int value) //Index starts from 0. Beginning (before head is )
{
    struct Node* p=head;
    for(int i=1; i<=index-1; i++)
    {
        p=p->nextPtr;
    }
    
    struct Node *ptr;
    ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->nextPtr=p->nextPtr;
    ptr->value=value;
    p->nextPtr=ptr;
}

void insertAtEnd(struct Node* head, int value)
{
    struct Node* q;
    q=head;
    while(q!=NULL)
        q=q->nextPtr;
    
    struct Node *ptr2;
    ptr2=(struct Node *)malloc(sizeof(struct Node));
    ptr2->nextPtr=NULL;
    ptr2->value=value;
    q->nextPtr=ptr2;
}

int main()
{
    //Creating pointers to nodes
    struct Node *head;
    struct Node *first;
    struct Node *second;

    //Creating a node by allocating it memeory by malloc
    head = (struct Node *)malloc(sizeof(struct Node)); //A malloc allocates contiguous blocks of main memory
    first = (struct Node *)malloc(sizeof(struct Node));
    second = (struct Node *)malloc(sizeof(struct Node));

    //adding value
    head->value=1;
    first->value=2;
    second->value=3;

    //linking nodes
    head->nextPtr=first;
    first->nextPtr=second;
    second->nextPtr=NULL;

    //Test for insertAtBegin
    int value1=0;
    head=insertAtBegin(head, value1);

    //Test for insertAtIndex
    insertAtIndex(head, 3, 4);

    //Test for insertAtEnd
    insertAtEnd(head, 5);

    printValue(head);
    return 0;
}

错误原因分析

insertAtEnd函数的循环逻辑存在致命错误:

  • 代码中while(q!=NULL)会让指针q持续向后遍历,直到q变为NULL(完全超出链表的最后一个节点)。
  • 此时尝试访问q->nextPtr,属于对空指针解引用,这是C语言中典型的未定义行为,直接触发Segmentation Fault。

正确的逻辑应该是遍历到链表的最后一个节点(即q->nextPtr == NULL的节点),再将新节点挂载到该节点的nextPtr上。

修复方案

基础修复(处理非空链表)

修改insertAtEnd的循环条件,确保q停在最后一个节点:

void insertAtEnd(struct Node* head, int value)
{
    struct Node* q = head;
    // 遍历至最后一个节点(q的下一个节点为NULL时停止)
    while(q->nextPtr != NULL)
        q = q->nextPtr;
    
    struct Node *ptr2 = (struct Node *)malloc(sizeof(struct Node));
    ptr2->nextPtr = NULL;
    ptr2->value = value;
    q->nextPtr = ptr2;
}

完整修复(支持空链表)

如果需要处理空链表(head为NULL)的情况,需要传递头指针的指针,以便修改头节点:

void insertAtEnd(struct Node** head, int value)
{
    struct Node *ptr2 = (struct Node *)malloc(sizeof(struct Node));
    ptr2->nextPtr = NULL;
    ptr2->value = value;

    // 空链表时直接将新节点设为头节点
    if(*head == NULL)
    {
        *head = ptr2;
        return;
    }

    struct Node* q = *head;
    while(q->nextPtr != NULL)
        q = q->nextPtr;
    
    q->nextPtr = ptr2;
}

调用时需要改为:

insertAtEnd(&head, 5);

其他潜在问题提示

  • insertAtIndex未处理index=0的场景:当index=0时,循环不会执行,代码会在头节点后插入新节点,但按索引定义,index=0应该插入到链表头部,此时需要修改头指针,建议参考insertAtBegin的实现逻辑。
  • 未检查malloc返回值:如果内存分配失败,malloc会返回NULL,后续操作会触发错误,建议添加if(new == NULL)的判断逻辑,避免空指针操作。

内容的提问来源于stack exchange,提问作者Soumil Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 11:40:00