使用read()读取PBM文件像素到2D数组时出现数据异常
问题描述
我的像素结构体定义如下:
typedef struct pixel{ int couleur[3];//rgb }pixel;
程序以PBM文件为输入,测试用的test.pbm内容如下:
P1 10 4 1111111111 0000000000 1010101010 0101010101
其中10是宽度,4是高度,1代表黑色,0代表白色。程序读取宽高后创建二维像素数组,用read()将PBM文件的值存入数组。
我的readImage函数代码如下:
pixel** readImage(char* filename,int *width,int *height){ //Reads the magic code char bufMagic[3]; int fd = open(filename,O_RDONLY); read(fd,bufMagic,3); bufMagic[2]='\0'; //if magic is not P1 error if(strncmp(bufMagic,"P1",2)!=0){ printf("ERREUR:Magic incorrect"); exit(1); } printf("BUFMAGIC:%s\n",bufMagic); char bufResolution[10]; int index = 1; char resTemp; //reads full string of resolution read(fd,&resTemp,sizeof(char)); bufResolution[0]=resTemp; while(resTemp!='\n'){ read(fd,&resTemp,sizeof(char)); bufResolution[index]=resTemp; index++; } bufResolution[index]='\0'; printf("BUFRES:%s",bufResolution); //splits the resolution into x and y char resx[5]; char resy[5]; int i =0; while(bufResolution[i]!=' '){ resx[i]=bufResolution[i]; i++; } i++; int j =i; while(bufResolution[i]!='\n'){ resy[i-j]=bufResolution[i]; i++; } int y= atoi(resy); int x = atoi(resx); //saves the pixels in a table char temp; pixel** tab = malloc(sizeof(*tab)*y); for(int i = 0;i<y;i++){ tab[i]=malloc(sizeof(tab)*x); } printf("x:%d y:%d\n",x,y); for(int i = 0;i<y;i++){ for(int j = 0;j<x;j++){ read(fd,&temp,sizeof(char)); // //so that the read skips a line without actually incrementing j if(temp=='\n'){ j--; } else//1 is black if(temp=='1'){ tab[i][j].couleur[0]=0; tab[i][j].couleur[1]=0; tab[i][j].couleur[2]=0; // printf("%d ",tab[i][j].couleur[0]/255); } if(temp=='0'){ tab[i][j].couleur[0]=255; tab[i][j].couleur[1]=255; tab[i][j].couleur[2]=255; // printf("%d ",tab[i][j].couleur[0]/255); } } // printf("\n"); } printf("DONE\n"); // //just to test the read //ISSUE IS HERE for (int i = 0; i < y; i++) { for (int j = 0; j < x; j++) { printf("%d", tab[i][j].couleur[1] / 255); } printf("\n"); } //sending the dimensions to main *width=x; *height=y; return tab; }
异常现象
读取循环中启用printf时,输出符合预期:
0000000000 1111111111 0101010101 1010101010
但最后遍历数组打印时,输出结果错乱:
0000000011 1111111101 0101010110 1010101010
明明读取时打印正确,为什么数组无法正确保存信息?
解决方案
核心问题:内存分配错误
问题出在二维数组每行的内存分配代码:
tab[i]=malloc(sizeof(tab)*x);
这里sizeof(tab)是指针的大小(通常为4或8字节),而非pixel结构体的大小。这导致每行分配的内存空间远小于实际需要,写入数据时会越界覆盖相邻行的内存,最终导致数组内容错乱。
修复代码
将该行改为分配x个pixel结构体的空间:
tab[i] = malloc(sizeof(pixel) * x);
或者用更安全的写法,避免类型写错:
tab[i] = malloc(sizeof(*tab[i]) * x);
额外优化建议
- 处理PBM注释:标准PBM文件允许包含
#开头的注释行,当前代码未处理,会导致读取逻辑出错。 - 改用标准IO函数:相比底层的
read(),fscanf或fgets更适合处理文本格式的PBM文件,能简化换行、空格的处理逻辑。 - 检查内存分配结果:每次
malloc后要判断返回值是否为NULL,避免空指针访问。 - 优化换行处理:当前读取像素时的
j--逻辑不够健壮,若文件中有连续空格或注释,会出现读取错误。
内容的提问来源于stack exchange,提问作者Motcho
相关产品推荐
相关产品推荐

