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; }
关键修改点
- 修复野指针问题:将
main中的int *h,*w;改为int h, w;,调用lerArq时传递它们的地址&h、&w,确保函数能正确写入行列数值。 - 处理输入缓冲区残留:添加
getchar();清除scanf("%c", &option);后残留的换行符,避免后续输入异常。 - 完善图像内存分配:修改
lerArq的参数为int ***I,实现对二维指针I的内存分配,同时添加内存分配失败的错误处理,避免内存泄漏。
内容的提问来源于stack exchange,提问作者GWA
相关产品推荐
相关产品推荐

