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

C语言统计文件单词次数程序为何触发段错误?

C程序段错误原因分析

问题背景

编写了一个统计目标单词在ham/spam消息中出现次数的C程序,单独测试各函数正常,但整合后触发段错误。编译时仅提示function returns address of local variable警告。程序代码如下:

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

int *countSH(char *filename, char *SentWord) {
    //opening file and checking whether it opens
    FILE *file = fopen(filename, "r");

    if (file == NULL) {
        perror("error while opening file");
        return NULL;
    }

    char line[500]; //line lenght = 500
    int hams = 0;
    int spams = 0;
    char *token = NULL;
    const char *word = SentWord;
    char *lineDupe;

    while(1) {
        if (feof(file)) { 
            break; //breaking the loop when getting to the end of the file
        } 

        if (fgets(line, sizeof(line), file) != NULL) { //if line != NULL
            lineDupe = strdup(line);
            token = strtok(lineDupe, " \t\n");
            while (token != NULL) {
                if (strcmp(token, word) == 0) {
                    if (line[0] == 'h') { //if line starts with h (ham)
                        hams++;
                    } else { //else it starts with s (spam)
                        spams = spams + 1;
                    }
                }
                token = strtok(NULL, " \t\n");
            }
        }
    }

    int countsh[2] = { hams, spams };

    if (hams == 0 && spams == 0) {
        printf("This word doesn’t occur in the text!");
    } else {
        printf("The word '%s' appears %d times in ham messages and %d times in spam messages.");
    }
    return countsh;
}

//this function gets the user input and saves the word for searching
char *getWord() {
    static char word[256];

    printf("Please enter a word to search for:\t");

    scanf("%255s", word);

    return word;
}

int main() {
    
    char *searchWord = getWord(); //assigning the searchword we got from the user to a var
    char *file = "preprocessed_dataset.txt";
    int *word_in_sh = countSH(file, searchWord);

    return 0;
}

编译警告:

try1_3.c: In function ‘countSH’:
try1_3.c:50:2: warning: function returns address of local variable [-Wreturn-local-addr]
  return countsh;

段错误触发原因

1. printf语句缺少必要参数

这是触发段错误的直接原因:
在countSH函数的else分支中,printf格式化字符串包含%s、%d、%d三个占位符,但没有传入对应的SentWord、hams、spams参数。这种情况下,程序会从栈上读取随机数据,导致栈访问越界,直接触发段错误。

2. 返回局部变量的地址

countSH函数中定义的int countsh[2]是栈上的局部变量,当函数执行完毕返回时,该变量所在的栈帧会被销毁,返回的地址变为野指针。虽然main函数中没有直接解引用这个指针,但这种行为属于未定义行为,可能间接导致程序崩溃。

3. feof的错误使用方式

当前循环先判断feof(file)再调用fgets,这会导致逻辑错误:当fgets读取到文件末尾时,feof标志才会被设置,此时循环会多执行一次,可能处理无效的空数据,引发未定义行为。

4. strdup内存泄漏(非段错误直接原因,但需修复)

每次循环中使用strdup复制行数据,但没有调用free(lineDupe)释放内存,会导致内存泄漏。

修复建议

  • 补全printf的参数:将else分支的printf改为:
    printf("The word '%s' appears %d times in ham messages and %d times in spam messages.", SentWord, hams, spams);
    
  • 避免返回局部变量地址:可以改用动态分配内存(malloc)存储结果,或者通过指针参数传递结果;
  • 修正feof的使用逻辑,用fgets返回值控制循环:
    while (fgets(line, sizeof(line), file) != NULL) {
        // 处理行数据
    }
    
  • 每次使用strdup后,调用free(lineDupe)释放内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:57:29