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

C语言使用malloc分配char**内存时出现segmentation fault问题求助

C语言代码问题排查与修复

核心报错原因

你遇到段错误的最直接原因是指针数组的内存分配大小计算错误:
你写的分配代码是:

ingredients = (char**)malloc(numIngredients*sizeof(char));

ingredients是char**类型,指向的是一组char*类型的指针,每个指针占4/8字节(依系统架构而定),而sizeof(char)仅为1字节,分配的内存空间远小于实际需要的大小。后续给ingredients[i]赋值时会越界访问非法内存,直接触发段错误。
修复方式为把分配语句修改为:

// 也可以写成 sizeof(*ingredients) 兼容性更好,修改指针类型时不需要同步改sizeof的参数
ingredients = malloc(numIngredients * sizeof(char*));

其他需要修复的潜在问题

  • 无文件打开校验:fopen执行失败时会返回NULL,后续直接操作空文件指针也会触发段错误,需要增加合法性判断:
in = fopen("input.txt", "r");
if (in == NULL) {
    perror("读取input.txt失败");
    return NULL;
}
  • 读取逻辑不符合需求:你要求读取文件的一整行作为食材名,但fscanf的%s格式符遇到空格、制表符就会终止读取,如果食材名包含空格会出现读取截断。建议替换为fgets读取整行,同时注意移除fgets自带的末尾换行符:
fgets(ingredients[i], MAX_ING, in);
// 移除末尾换行符
char *newline = strchr(ingredients[i], '\n');
if (newline) *newline = '\0';
  • 无内存分配校验:每次malloc调用后都需要判断返回值是否为NULL,避免内存分配失败后操作空指针。
  • 冗余的返回值强制转换:C标准允许void*隐式转换为任意指针类型,malloc返回值不需要强制转换,多余的转换反而可能隐藏未引入stdlib.h头文件的问题。

修复后完整参考代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_ING 128 // 可根据实际需求修改大小

char** readIngredients(int numIngredients){
    // 入参合法性校验
    if (numIngredients <= 0) {
        return NULL;
    }
    FILE *in = fopen("input.txt", "r");
    if (in == NULL) {
        perror("打开input.txt失败");
        return NULL;
    }

    char** ingredients = malloc(numIngredients * sizeof(*ingredients));
    if (ingredients == NULL) {
        perror("分配指针数组失败");
        fclose(in);
        return NULL;
    }

    for(int i=0; i<numIngredients; i++){
        ingredients[i] = malloc(MAX_ING * sizeof(char));
        if (ingredients[i] == NULL) {
            perror("分配字符串内存失败");
            // 分配失败时释放已申请的内存避免泄漏
            for(int j=0; j<i; j++) {
                free(ingredients[j]);
            }
            free(ingredients);
            fclose(in);
            return NULL;
        }
        // 读取整行
        if (fgets(ingredients[i], MAX_ING, in) == NULL) {
            // 读取失败处理
            perror("读取行失败");
            for(int j=0; j<=i; j++) {
                free(ingredients[j]);
            }
            free(ingredients);
            fclose(in);
            return NULL;
        }
        // 移除换行符
        char *newline = strchr(ingredients[i], '\n');
        if (newline) {
            *newline = '\0';
        }
    }

    fclose(in);
    return ingredients;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:39:02