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

调用fclose()触发Segmentation Fault问题求助

问题描述

编写函数读取仅含数字的PREVIOUSSTOP文件,根据数字将info文件定位到对应位置(数字为x则前移x个句子),但调用fclose(stop)时出现Segmentation Fault,文件指针非NULL,gdb调试回溯全为问号,请求修复。

原代码
#include <stdio.h>
#include <stdlib.h>
int stopnum = 0;

void GetInfoFromFile(FILE* info, char* Sentence1) {
    int i = 0;
    while (1) {
        char c;
        c = fgetc(info);
        Sentence1[i] = c;
        if (Sentence1[i] == '.' || Sentence1[i] == '!' || Sentence1[i] == '?') {
            break;
        }
        i++;
    }
    Sentence1[i + 1] = '\0';
}
void RestartPreviousTrainingSession(FILE* info) {
    FILE* stop = fopen("PREVIOUSSTOP", "r");
    if (stop != NULL) {
        char* stopstr = malloc(32);
        fgets(stopstr, 32, stop);
        int stopint = strtol(stopstr, NULL, 10);
        stopnum = stopint;
        char dummysentence[400];
        for (int i = 0; i != stopint; i++) {
            GetInfoFromFile(info, dummysentence);
        }
        /* segmentation fault occurs here */
        fclose(stop);
    } else {
        printf("OOPS\n");
    }
}
int main() {
    FILE* f = fopen("wiki.train.tokens", "r");
    RestartPreviousTrainingSession(f);
    fclose(f);
}
问题分析与修复方案

段错误核心原因是缓冲区溢出破坏了栈上的文件指针stop,具体问题点和修复如下:

1. GetInfoFromFile未处理文件结束与缓冲区越界

  • 原代码用char存储fgetc返回值,无法正确识别EOF(EOF是int类型的-1,若char为无符号类型会被转为255,导致循环无法终止)。
  • 未限制写入缓冲区的长度,当句子超长或文件提前结束时,会越界写入dummysentence,破坏栈上的stop指针等数据。

修复后的GetInfoFromFile:

void GetInfoFromFile(FILE* info, char* Sentence1, int max_len) {
    if (!info || !Sentence1 || max_len <= 0) {
        return;
    }

    int i = 0;
    int c;
    while ((c = fgetc(info)) != EOF) {
        // 预留最后一个位置存'\0',避免缓冲区溢出
        if (i >= max_len - 1) {
            break;
        }
        Sentence1[i] = (char)c;
        if (Sentence1[i] == '.' || Sentence1[i] == '!' || Sentence1[i] == '?') {
            i++;
            break;
        }
        i++;
    }
    Sentence1[i] = '\0';
}

2. 未检查malloc返回值与内存泄漏

  • malloc(32)可能失败返回NULL,此时调用fgets会直接崩溃。
  • 分配的stopstr未释放,存在内存泄漏。

3. 循环与参数合法性问题

  • 原循环用i != stopint,若stopint为负数会陷入死循环,改为i < stopint并提前判断stopint的合法性。
完整修复代码
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int stopnum = 0;

void GetInfoFromFile(FILE* info, char* Sentence1, int max_len) {
    if (!info || !Sentence1 || max_len <= 0) {
        return;
    }

    int i = 0;
    int c;
    while ((c = fgetc(info)) != EOF) {
        if (i >= max_len - 1) {
            break;
        }
        Sentence1[i] = (char)c;
        if (Sentence1[i] == '.' || Sentence1[i] == '!' || Sentence1[i] == '?') {
            i++;
            break;
        }
        i++;
    }
    Sentence1[i] = '\0';
}

void RestartPreviousTrainingSession(FILE* info) {
    if (!info) {
        return;
    }

    FILE* stop = fopen("PREVIOUSSTOP", "r");
    if (stop != NULL) {
        char* stopstr = malloc(32);
        if (!stopstr) {
            fclose(stop);
            return;
        }

        // 读取失败或为空时直接返回
        if (!fgets(stopstr, 32, stop)) {
            free(stopstr);
            fclose(stop);
            return;
        }

        // 跳过开头空白字符,确保strtol正确解析
        char* ptr = stopstr;
        while (isspace((unsigned char)*ptr)) {
            ptr++;
        }

        int stopint = strtol(ptr, NULL, 10);
        // 过滤无效的负数或0
        if (stopint <= 0) {
            free(stopstr);
            fclose(stop);
            return;
        }

        stopnum = stopint;
        char dummysentence[400];
        for (int i = 0; i < stopint; i++) {
            GetInfoFromFile(info, dummysentence, sizeof(dummysentence));
            // 文件提前结束时终止循环
            if (feof(info)) {
                break;
            }
        }

        free(stopstr);
        fclose(stop);
    } else {
        printf("OOPS\n");
    }
}

int main() {
    FILE* f = fopen("wiki.train.tokens", "r");
    if (f) {
        RestartPreviousTrainingSession(f);
        fclose(f);
    } else {
        printf("Failed to open wiki.train.tokens\n");
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:44:58