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

添加联系人的do/while循环触发Segmentation Fault问题求助

解决你的addContact函数段错误问题

嘿,我仔细看了你的addContact函数代码,触发段错误主要是几个容易忽略的细节问题,我帮你逐一拆解并给出修复方案:

1. 未初始化的FILE *fptr直接导致崩溃

你声明了FILE *fptr但从来没有打开文件就直接调用fprintf,这会让程序访问非法内存地址,直接触发段错误。

修复方法:
在使用fptr前,用fopen打开目标文件,同时要检查文件是否成功打开,避免后续操作出错:

fptr = fopen("contacts.txt", "a+"); // 以追加+读取模式打开,可根据需求调整模式
if (fptr == NULL) {
    perror("Failed to open file");
    free(newPtr); // 避免内存泄漏
    return;
}

记得在文件操作完成后用fclose(fptr);关闭文件。

2. 未初始化的prevPtr引发野指针访问

当链表为空时(*sPtr是NULL),crntPtr初始化为NULL,第二个while循环(while (crntPtr != NULL && ...))根本不会执行,此时prevPtr是未初始化的野指针。后续判断if (prevPtr == NULL)时,野指针的值是随机的,大概率不会等于NULL,程序会进入else分支访问prevPtr->next,直接触发段错误。

修复方法:
显式将prevPtr初始化为NULL:

contactPtr prevPtr = NULL;

3. fflush(stdin)是未定义行为

标准C中,fflush只对输出流有效,对输入流stdin调用fflush是未定义行为,不同编译器可能有不同表现,甚至导致异常。

修复方法:
用自定义函数清空输入缓冲区:

void clearInputBuffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

然后把所有fflush(stdin);替换成clearInputBuffer();。

4. 不安全的gets函数存在溢出风险

gets函数不会检查输入长度,很容易导致缓冲区溢出,这也是潜在的崩溃隐患(输入过长时会触发)。

修复方法:
用fgets替代gets,同时处理掉fgets读取的换行符:

// 读取姓名
printf("Enter contact name: ");
clearInputBuffer();
fgets(newPtr->name, sizeof(newPtr->name), stdin);
newPtr->name[strcspn(newPtr->name, "\n")] = '\0';

// 读取电话号码同理
printf("Enter contact number: ");
clearInputBuffer();
fgets(newPtr->phoneNum, sizeof(newPtr->phoneNum), stdin);
newPtr->phoneNum[strcspn(newPtr->phoneNum, "\n")] = '\0';

修复后的完整函数示例

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

typedef struct Contact {
    char name[50];
    char phoneNum[20];
    struct Contact *next;
} Contact;
typedef Contact* contactPtr;

void clearInputBuffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

void addContact(contactPtr *sPtr) {
    FILE *fptr;
    contactPtr checkPtr = *sPtr;
    contactPtr crntPtr = checkPtr;
    contactPtr prevPtr = NULL; // 显式初始化prevPtr
    contactPtr newPtr;
    int check = 0;

    // 检查malloc是否成功
    newPtr = (Contact *)malloc(sizeof(Contact));
    if (newPtr == NULL) {
        perror("Failed to allocate memory");
        return;
    }

    printf("Enter contact name: ");
    clearInputBuffer();
    fgets(newPtr->name, sizeof(newPtr->name), stdin);
    newPtr->name[strcspn(newPtr->name, "\n")] = '\0';

    do {
        checkPtr = crntPtr;
        check = 0;
        printf("Enter contact number: ");
        clearInputBuffer();
        fgets(newPtr->phoneNum, sizeof(newPtr->phoneNum), stdin);
        newPtr->phoneNum[strcspn(newPtr->phoneNum, "\n")] = '\0';

        for (; checkPtr != NULL; checkPtr = checkPtr->next) {
            if (strcmp(checkPtr->phoneNum, newPtr->phoneNum) == 0) {
                printf("Phone No is already available\n");
                check = 1;
                break;
            }
        }
    } while (check);

    // 打开文件并检查
    fptr = fopen("contacts.txt", "a+");
    if (fptr == NULL) {
        perror("Failed to open file");
        free(newPtr);
        return;
    }
    fprintf(fptr, "\n%s\n", newPtr->name);
    fprintf(fptr, "%s\n", newPtr->phoneNum);
    fclose(fptr);

    // 找到正确的插入位置
    crntPtr = *sPtr;
    while (crntPtr != NULL && strcmp(newPtr->name, crntPtr->name) > 0) {
        prevPtr = crntPtr;
        crntPtr = crntPtr->next;
    }

    if (prevPtr == NULL) {
        newPtr->next = *sPtr;
        *sPtr = newPtr;
    } else {
        prevPtr->next = newPtr;
        newPtr->next = crntPtr;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:27:46