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

C语言中为何出现Segmentation Fault错误?动态存单词遇问题

问题分析与修复

你的代码出现段错误的核心原因是指针数组的内存分配大小计算错误,同时还有多处内存管理和字符串操作的问题,下面逐一拆解并修复:

主要错误点

  • 指针数组分配字节数不足:dictionaryOfWords是char**类型,每个元素是一个char*指针,你用malloc(1)和realloc(..., numberOfWords + 1)只分配了1字节或numberOfWords+1字节,远不够存储指针(通常指针是4/8字节),导致数组越界写入,触发段错误。
  • word的内存泄漏与双重释放:先malloc给word,马上用returnWord的返回值覆盖指针,之前分配的内存直接泄漏;如果returnWord返回的是line的子指针(比如去掉换行后的line),后续free(word)+free(line)会导致双重释放,触发未定义行为。
  • else分支的野指针与strcat误用:dictionaryOfWords[numberOfWords]是新扩展的数组位置,未初始化就调用realloc,属于操作野指针;而且strcat要求目标字符串已有\0结尾,刚分配的内存没有初始化,会导致越界访问。
  • getline的错误使用:getline会自动管理line的内存,每次循环free(line)后下一次getline虽然能重新分配,但完全没必要,还容易出问题。

修复后的代码

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

// 实现slength:计算不含换行的字符串长度
size_t slength(const char *line) {
    size_t len = strlen(line);
    if (len > 0 && line[len-1] == '\n') {
        return len - 1;
    }
    return len;
}

// 实现returnWord:返回去掉换行的新分配字符串
char* returnWord(const char *line) {
    size_t len = slength(line);
    char *word = malloc(len + 1); // 额外分配1字节存'\0'
    if (!word) exit(EXIT_FAILURE);
    strncpy(word, line, len);
    word[len] = '\0';
    return word;
}

int main(void) {
    FILE *fp;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    char** dictionaryOfWords = NULL;
    int numberOfWords = 0;
    char* word;

    fp = fopen("words.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        printf("Retrieved line of length %zu :\n", read);
        printf("%s", line);

        // 获取处理后的单词
        word = returnWord(line);
        printf("test 1\n");

        // 扩展指针数组:分配足够的指针空间
        char** temp = realloc(dictionaryOfWords, (numberOfWords + 1) * sizeof(char*));
        if (!temp) {
            perror("realloc failed");
            // 内存清理避免泄漏
            for (int i = 0; i < numberOfWords; i++) {
                free(dictionaryOfWords[i]);
            }
            free(dictionaryOfWords);
            free(word);
            free(line);
            fclose(fp);
            exit(EXIT_FAILURE);
        }
        dictionaryOfWords = temp;

        // 为当前单词分配内存并复制内容
        dictionaryOfWords[numberOfWords] = malloc(strlen(word) + 1);
        if (!dictionaryOfWords[numberOfWords]) {
            perror("malloc failed");
            // 内存清理
            free(word);
            for (int i = 0; i < numberOfWords; i++) {
                free(dictionaryOfWords[i]);
            }
            free(dictionaryOfWords);
            free(line);
            fclose(fp);
            exit(EXIT_FAILURE);
        }
        strcpy(dictionaryOfWords[numberOfWords], word);

        numberOfWords++;
        free(word); // 释放临时单词内存
    }

    // 使用完后清理所有动态内存
    for (int i = 0; i < numberOfWords; i++) {
        free(dictionaryOfWords[i]);
    }
    free(dictionaryOfWords);
    free(line);
    fclose(fp);
    exit(EXIT_SUCCESS);
}

关键修复说明

  1. 指针数组分配正确大小:用(numberOfWords + 1) * sizeof(char*)计算所需字节数,确保能容纳足够的指针。
  2. 检查内存分配结果:realloc和malloc都可能失败,必须检查返回值,避免空指针操作。
  3. 修正word的内存管理:确保returnWord正确分配新内存,用完后释放;不再重复malloc后覆盖指针。
  4. 替换strcat为strcpy:新分配的单词内存是空的,直接用strcpy复制内容即可,无需strcat。
  5. 正确使用getline:只在循环结束后释放line,避免每次循环重复释放和分配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:06:20