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

链表搜索功能异常:SIGBUS错误与内存泄漏问题排查

C语言链表程序崩溃问题排查与修复

问题现象

编写的C语言链表程序,逻辑参考自公开资源,他人运行正常但本地出现以下问题:

  • 程序通过STDIN每行输入单词,运行时提示Process finished with exit code 138 (interrupted by signal 10: SIGBUS)
  • 调试发现卡在search函数的if (strcmp(var->word, searched) == 0)行
  • 程序启动后能输出部分内容,随后崩溃,调试显示temp->word字段内存读取失败:read memory from 0x6c62430000600000 failed (0 of 1 bytes read)

错误根源分析

  1. Delete函数传参错误:
    Delete函数接收的head是值传递,删除头节点时,修改的是函数内部的局部head变量,而非主函数中的全局head指针。这会导致主函数中的head依然指向已被释放的内存,后续访问(如search、Count)时触发野指针,引发内存访问错误。

  2. Free_All函数内存泄漏:
    每个节点的word通过malloc分配,但Free_All仅释放节点结构体本身,未释放word指向的内存,造成内存泄漏。

  3. Insert函数冗余赋值:
    new_node->word = strcpy(new_node->word, word);中,strcpy已返回目标指针,此处赋值属于冗余操作。

  4. main函数缓冲区溢出风险:
    定义的word[20]和to_delete[15]未限制输入长度,若输入超过数组容量会导致缓冲区溢出。

修复方案

1. 修正Delete函数传参方式

将Delete函数的head改为指针的指针,确保修改同步到主函数:

void Delete(struct node** head, char* to_delete) {
    struct node *temp = *head;
    struct node *prev = NULL;
    while(temp != NULL){
        if(strcmp(temp->word, to_delete) == 0)
        {
            if(prev == NULL){
                *head = (*head)->next;
                free(temp->word); // 先释放word内存
                free(temp);
                return;
            }
            else{
                prev->next = temp->next;
                free(temp->word); // 先释放word内存
                free(temp);
                return;
            }
        }
        prev = temp;
        temp = temp->next;
    }
}

同时在main函数中调用时传入&head:

Delete(&head, to_delete);

2. 完善Free_All函数,释放word内存

void Free_All(struct node* head){
    struct node* temp;
    temp = head;

    while( temp != NULL ){
        head= head->next;
        free(temp->word); // 释放节点的word内存
        free(temp);
        temp = head;
    }
}

3. 简化Insert函数冗余赋值

将new_node->word = strcpy(new_node->word, word);改为:

strcpy(new_node->word, word);

也可使用strdup简化(POSIX标准,兼容需求可手动实现):

new_node->word = strdup(word);

4. 修复main函数缓冲区溢出风险

修改scanf调用,限制输入长度:

temp = scanf("%19s", word); // word数组长度20,留1位给终止符
// ...
scanf("%19s", word);
// ...
scanf("%14s", to_delete); // to_delete数组长度15,留1位给终止符

修正后的完整代码

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

struct node{
    char* word;
    struct node* next;
};

int search(struct node** head, char* searched);
void Print(struct node* head);
void Free_All(struct node* head);
void Insert(struct node** head, char* word);
void Delete(struct node** head, char* to_delete);
int Count(struct node* head);

int main() {
    static struct node *head = NULL;

    int temp;
    char word[20];

    for (;;) {
        temp = scanf("%19s", word);

        if (strcmp(word, "Print") == 0) {
            Print(head);
        }
        else if (strcmp(word, "Stop") == 0) {
            break;
        } 
        else if (temp == EOF) {
            Free_All(head);
            return 0;
        } 
        else {
            Insert(&head, word);
        }
    }

    scanf("%19s", word);
    int found = search(&head, word);

    if (found == 0) {
        printf("!! ERROR !!");
        Free_All(head); // 错误时也要释放内存
        return 1;
    }

    else {
        char to_delete[15];
        scanf("%14s", to_delete);
        Delete(&head, to_delete);

        // DO OTHER STUFF
    }

    int count = Count(head);
    printf("Remaining nodes: %d\n", count);
    Free_All(head);
    return 0; // 补充main函数的返回值
}

int search(struct node** head, char* searched) {
    struct node* var = *head;

    while (var != NULL) {
        if (strcmp(var->word, searched) == 0)
            return 1;
        var = var->next;
    }
    return 0;
}

void Print(struct node* head){
    struct node* temp = head;
    while (temp) {
        printf("%s \n", temp->word);
        temp = temp->next;
    }
}

void Free_All(struct node* head){
    struct node* temp;
    temp = head;

    while( temp != NULL ){
        head= head->next;
        free(temp->word);
        free(temp);
        temp = head;
    }
}

void Insert(struct node** head, char* word)
{
    // Create new node
    struct node* new_node = (struct node*)malloc(sizeof(struct node));
    new_node->word = malloc(strlen(word)+1);
    strcpy(new_node->word, word);
    new_node->next = NULL;

    if (*head == NULL || strcmp((*head)->word, new_node->word) >= 0) {
        new_node->next = *head;
        *head = new_node;
    }
    else {
        struct node* temp = *head;
        while (temp->next != NULL && strcmp(temp->next->word, new_node->word) < 0) {
            temp = temp->next;
        }
        new_node->next = temp->next;
        temp->next = new_node;
    }
}

void Delete(struct node** head, char* to_delete) {
    struct node *temp = *head;
    struct node *prev = NULL;
    while(temp != NULL){
        if(strcmp(temp->word, to_delete) == 0)
        {
            if(prev == NULL){
                *head = (*head)->next;
                free(temp->word);
                free(temp);
                return;
            }
            else{
                prev->next = temp->next;
                free(temp->word);
                free(temp);
                return;
            }
        }
        prev = temp;
        temp = temp->next;
    }
}

int Count(struct node* head){
    int counter = 0;
    struct node* var = head;
    while (var != NULL)
    {
        counter++;
        var = var->next;
    }
    return counter;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:18:18