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

C语言中调用strcmp()触发Segmentation Fault问题排查与修复

问题与修复方案

问题描述

调用getStop函数时,代码总是在strcmp处崩溃并返回Segmentation Error,插入printf("%s", stop->name);后,崩溃点转移到printf处。以下是最小可复现代码:

原getStop函数代码

stop_t *getStop(char *name) {
    node_t *current = stop_list_head;
    stop_t *stop;

    while (current != NULL) {
        stop = current->stop;
        if (stop != NULL) {
            if (stop->name != NULL) {
                if (strcmp(stop->name, name) == 0) {
                    return stop;
                }
            }
        }
        current = current->next;
    }
    return NULL;
}

完整最小可复现代码

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

#define MAX_LENGTH_STOP 50

typedef struct {
    int routeCounter;
    double latitude;
    double longitude;
    char name[MAX_LENGTH_STOP + 1];
} stop_t;

typedef struct node {
    stop_t *stop;
    struct node *next;
} node_t;

void printStopList();

node_t *stop_list_head = NULL;

int main() {
    stop_t *stopPtr = NULL;
    stop_t stop;
    char name[MAX_LENGTH_STOP + 1];

    /* Input Example: Praca de Espanha ; */
    fgets(name, BUFSIZ, stdin);

    stopPtr = getStop(name);
    /* Create new stop if it doesn't exist already, else print error.*/
    if (stopPtr == NULL) {
        generateStop(name);
    } else {
        printf("<Error 01>: Stop already exists.\n");
    }
}

/* Determines if the stop already exists based on the name */
stop_t *getStop(char *name) {
    node_t *current = stop_list_head;
    stop_t *stop;

    while (current != NULL) {
        stop = current->stop;
        if (stop != NULL) {
            if (stop->name != NULL) {
                if (strcmp(stop->name, name) == 0) {
                    return stop;
                }
            }
        }
        current = current->next;
    }
    return NULL;
}

/* Generates a stop instance and adds it to the global linked list*/
void generateStop(char name[]) {
    stop_t *stop = NULL;

    stop = (stop_t *)malloc(sizeof(stop_t));

    strcpy(stop->name, name);
    stop->routeCounter = 0;
    addStopToList(stop);
    free(stop);
}

/* Adds created stops to a global linked list (stop_list_head)*/
void addStopToList(stop_t *stop) {

    node_t *new_node = (node_t *)malloc(sizeof(node_t));
    node_t *current;

    new_node->stop = stop;
    new_node->next = NULL;

    if (stop_list_head == NULL) {
        stop_list_head = new_node;
    } else {
        current = stop_list_head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = new_node;
    }

    free(new_node);
}

核心错误分析

崩溃的根源是两处非法的内存释放:

  1. generateStop中释放了stop指针:用malloc创建stop实例后,将其加入链表立刻调用free(stop),导致链表中存储的stop指针变成野指针,后续访问stop->name时会触发段错误。
  2. addStopToList中释放了new_node:new_node是链表的节点,刚加入链表就free(new_node),导致链表节点本身被释放,遍历链表时会访问非法内存。

另外还有一个次要问题:fgets会读取输入末尾的换行符\n,导致存储的名字带换行符,后续调用getStop时会因字符串不匹配重复创建节点,需要额外处理去掉换行符。

修复后的代码

修改generateStop函数

移除free(stop);,保留malloc出来的stop实例,并处理换行符:

void generateStop(char name[]) {
    stop_t *stop = NULL;

    stop = (stop_t *)malloc(sizeof(stop_t));
    // 去掉fgets读取的换行符
    name[strcspn(name, "\n")] = '\0';
    strcpy(stop->name, name);
    stop->routeCounter = 0;
    addStopToList(stop);
}

修改addStopToList函数

移除free(new_node);,保留链表节点:

void addStopToList(stop_t *stop) {
    node_t *new_node = (node_t *)malloc(sizeof(node_t));
    node_t *current;

    new_node->stop = stop;
    new_node->next = NULL;

    if (stop_list_head == NULL) {
        stop_list_head = new_node;
    } else {
        current = stop_list_head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = new_node;
    }
}

完整修复后的代码

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

#define MAX_LENGTH_STOP 50

typedef struct {
    int routeCounter;
    double latitude;
    double longitude;
    char name[MAX_LENGTH_STOP + 1];
} stop_t;

typedef struct node {
    stop_t *stop;
    struct node *next;
} node_t;

node_t *stop_list_head = NULL;

int main() {
    stop_t *stopPtr = NULL;
    char name[MAX_LENGTH_STOP + 1];

    /* Input Example: Praca de Espanha */
    fgets(name, sizeof(name), stdin); // 限制读取长度避免缓冲区溢出

    stopPtr = getStop(name);
    if (stopPtr == NULL) {
        generateStop(name);
    } else {
        printf("<Error 01>: Stop already exists.\n");
    }
}

stop_t *getStop(char *name) {
    node_t *current = stop_list_head;
    stop_t *stop;
    char stripped_name[MAX_LENGTH_STOP + 1];
    strcpy(stripped_name, name);
    // 统一去掉换行符,保证匹配一致性
    stripped_name[strcspn(stripped_name, "\n")] = '\0';

    while (current != NULL) {
        stop = current->stop;
        if (stop != NULL && strcmp(stop->name, stripped_name) == 0) {
            return stop;
        }
        current = current->next;
    }
    return NULL;
}

void generateStop(char name[]) {
    stop_t *stop = (stop_t *)malloc(sizeof(stop_t));
    name[strcspn(name, "\n")] = '\0';
    strcpy(stop->name, name);
    stop->routeCounter = 0;
    addStopToList(stop);
}

void addStopToList(stop_t *stop) {
    node_t *new_node = (node_t *)malloc(sizeof(node_t));
    node_t *current;

    new_node->stop = stop;
    new_node->next = NULL;

    if (stop_list_head == NULL) {
        stop_list_head = new_node;
    } else {
        current = stop_list_head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = new_node;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:35:25