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

使用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);

额外优化建议

  1. 处理PBM注释:标准PBM文件允许包含#开头的注释行,当前代码未处理,会导致读取逻辑出错。
  2. 改用标准IO函数:相比底层的read(),fscanf或fgets更适合处理文本格式的PBM文件,能简化换行、空格的处理逻辑。
  3. 检查内存分配结果:每次malloc后要判断返回值是否为NULL,避免空指针访问。
  4. 优化换行处理:当前读取像素时的j--逻辑不够健壮,若文件中有连续空格或注释,会出现读取错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:20:35