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

C语言读取图像文本文件时出现Segmentation Fault问题求助

C语言读取P2格式图像文件触发Segmentation Fault的解决方法

问题场景

编写C语言代码读取代表黑白图像的P2格式.txt文件时,执行到打印图像行列数步骤触发Segmentation Fault错误,无法定位问题。

原代码

#include <stdlib.h>
#include <stdio.h>
#define MAX 256

int lerArq(int **I, char filename[MAX],int *h,int *w);

int main(){

    char option;
    char filename[MAX];
    int *h,*w;
    int **I;
    int i,j;

    printf("Q Quit (terminar o programa)\n"
           "L Ler um arquivo de imagens\n"
           "S Salvar a imagem em arquivo\n"
           "M Manter a imagem-entrada anterior\n"
           "B Binarizar a imagem-entrada\n"
           "C Calcular Contorno da imagem-entrada\n"
           "F Filtrar a imagem-entrada\n"
           "I Inverter a imagem-entrada\n"
           "R Rotular a imagem-entrada\n");
    printf("Digite a opção:\n");
    scanf("%c", &option);

    if(option=='l' || option=='L'){
        printf("Digite o nome do aquivo:\n");
        scanf("%s", filename);
        lerArq(I,filename,h,w);

    }


    return 0;
}

int lerArq(int **I, char filename[MAX],int *h,int *w){
    FILE *arq;
    arq=fopen(filename, "r");
    char line[5];
    int i,j;

    if(arq == NULL) {
        printf("ERRO: Não foi possível localizar o arquivo: %s!\n", filename);
        return 0;
    }

    fscanf(arq, "%s", line);
    fscanf(arq, "%d %d", w, h);
    fscanf(arq, "%s", line);


    printf("%d %d\n", *h, *w);

    fclose(arq);

    return 1;

}

待读取的P2格式文件内容

P2
10 10
255
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 1 1 1 0
1 1 0 0 1 0 0 1 1 0
0 0 1 0 0 1 0 0 1 0
0 0 1 0 0 1 0 0 1 0
0 0 0 1 0 1 0 0 1 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0

错误原因与解决方案

核心错误

main函数中声明的int *h,*w;是未初始化的野指针,直接传递给lerArq函数后,fscanf(arq, "%d %d", w, h);和printf("%d %d", *h, *w);会尝试对野指针进行解引用,访问非法内存地址,直接触发Segmentation Fault。

另外,scanf("%c", &option);读取选项后,输入缓冲区会残留换行符,后续若有其他字符输入操作可能出现异常,建议一并处理。

修正后的代码

#include <stdlib.h>
#include <stdio.h>
#define MAX 256

int lerArq(int ***I, char filename[MAX], int *h, int *w);

int main(){

    char option;
    char filename[MAX];
    // 将h、w改为普通int变量,后续传地址给函数
    int h, w;
    int **I = NULL;
    int i,j;

    printf("Q Quit (terminar o programa)\n"
           "L Ler um arquivo de imagens\n"
           "S Salvar a imagem em arquivo\n"
           "M Manter a imagem-entrada anterior\n"
           "B Binarizar a imagem-entrada\n"
           "C Calcular Contorno da imagem-entrada\n"
           "F Filtrar a imagem-entrada\n"
           "I Inverter a imagem-entrada\n"
           "R Rotular a imagem-entrada\n");
    printf("Digite a opção:\n");
    scanf("%c", &option);
    // 清除输入缓冲区的换行符
    getchar();

    if(option=='l' || option=='L'){
        printf("Digite o nome do aquivo:\n");
        scanf("%s", filename);
        // 传h和w的地址,I的地址(后续需要分配内存)
        lerArq(&I, filename, &h, &w);

        // 测试打印行列数
        printf("Imagem dimensões: %d linhas x %d colunas\n", h, w);

        // 后续如果要使用图像数据,记得释放内存
        if(I != NULL){
            for(i=0; i<h; i++){
                free(I[i]);
            }
            free(I);
        }
    }

    return 0;
}

int lerArq(int ***I, char filename[MAX], int *h, int *w){
    FILE *arq;
    arq = fopen(filename, "r");
    char line[5];
    int i,j;

    if(arq == NULL) {
        printf("ERRO: Não foi possível localizar o arquivo: %s!\n", filename);
        return 0;
    }

    fscanf(arq, "%s", line);
    // 正确读取行列数到h和w指向的内存
    fscanf(arq, "%d %d", w, h);
    fscanf(arq, "%s", line);

    printf("%d %d\n", *h, *w);

    // 分配图像内存(如果需要存储像素数据)
    *I = (int**)malloc(*h * sizeof(int*));
    if(*I == NULL){
        printf("ERRO: Falha ao alocar memória!\n");
        fclose(arq);
        return 0;
    }
    for(i=0; i<*h; i++){
        (*I)[i] = (int*)malloc(*w * sizeof(int));
        if((*I)[i] == NULL){
            printf("ERRO: Falha ao alocar memória para linha %d!\n", i);
            // 释放已分配的内存
            for(j=0; j<i; j++){
                free((*I)[j]);
            }
            free(*I);
            fclose(arq);
            return 0;
        }
        // 读取每行像素数据
        for(j=0; j<*w; j++){
            fscanf(arq, "%d", &((*I)[i][j]));
        }
    }

    fclose(arq);
    return 1;
}

关键修改点

  1. 修复野指针问题:将main中的int *h,*w;改为int h, w;,调用lerArq时传递它们的地址&h、&w,确保函数能正确写入行列数值。
  2. 处理输入缓冲区残留:添加getchar();清除scanf("%c", &option);后残留的换行符,避免后续输入异常。
  3. 完善图像内存分配:修改lerArq的参数为int ***I,实现对二维指针I的内存分配,同时添加内存分配失败的错误处理,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:50:51