Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
199 views
in Technique[技术] by (71.8m points)

c - diffent image file size causes segmentation fault when memory is freed

I was learning how to add textures in OpenGL , and decided for educational purposes to not use a library like "stb_image.h" to load images , but instead to write my own one for .bmp images.

The dimensions of the image I was using is 1920x1080 (full HD) and the file size was 6.2?MB (6,220,922 bytes). After loading the image and converting it from blue,green,red (BGR) to red,green,blue (RGB) I decided to free the BGR version but when doing that a "segmentation fault (core dumped)" happened.

One of the stuff I tried was to use a different image and this causes the error to go away. The new image resolution is 1280x1920, file size of 7.4?MB (7,372,922 bytes).

I decided to flip the dimensions of the earlier image (from 1920x1080 to 1080x1920) and the "segmentation fault (core dumped)" went back.

This is the relevant code (removed all OpenGL and GLFW stuff) in C.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

typedef struct 
{
   uint16_t type;
   uint32_t size;
   uint16_t reserved1;
   uint16_t reserved2;
   uint32_t offbit;
}BITMAPFILEHEADER;

typedef struct {
    uint32_t size;
    uint32_t width;
    uint32_t height;
    uint16_t planes;
    uint16_t bitcount;
    uint32_t comprestiontype;
    uint32_t sizeimage;
    uint32_t xres;
    uint32_t yres;
    uint32_t crlused;
    uint32_t crlimportant;
}BITMAPINFOHEADER;

typedef struct{
    uint8_t r;
    uint8_t g;
    uint8_t b;
}RGB;

void ReadFileHeader(FILE* file, BITMAPFILEHEADER* fileHeader){
    fread(&(fileHeader->type),2,1,file);
    fread(&(fileHeader->size),4,1,file);
    fread(&(fileHeader->reserved1),2,1,file);
    fread(&(fileHeader->reserved2),2,1,file);
    fread(&(fileHeader->offbit),4,1,file);
}

void ReadInfoHeader(FILE* file, BITMAPINFOHEADER* fileHeader){
    fread(&(fileHeader->size),4,1,file);
    fread(&(fileHeader->width),4,1,file);
    fread(&(fileHeader->height),4,1,file);
    fread(&(fileHeader->planes),2,1,file);
    fread(&(fileHeader->bitcount),2,1,file);
    fread(&(fileHeader->comprestiontype),4,1,file);
    fread(&(fileHeader->sizeimage),4,1,file);
    fread(&(fileHeader->xres),4,1,file);
    fread(&(fileHeader->yres),4,1,file);
    fread(&(fileHeader->crlused),4,1,file);
    fread(&(fileHeader->crlimportant),4,1,file);
}


unsigned char* ReadBMP(const char * p_path, int* width, int* hight){
    FILE* image = fopen(p_path,"rb");
    if(image == NULL){
        printf("file not found
");
    }
    BITMAPFILEHEADER file_header;
    BITMAPINFOHEADER info_header;

    ReadFileHeader(image,&file_header);
    ReadInfoHeader(image,&info_header);

    if (width != NULL)
    {
        *width = info_header.width;
    }
    
    if (hight != NULL)
    {
        *hight = info_header.height;
    }

    unsigned char* pixelData = (unsigned char*)malloc(sizeof(RGB)*info_header.width*info_header.height);
    fread(pixelData,sizeof(RGB),info_header.width*info_header.height,image);
    fclose(image);
    return pixelData;
}

unsigned char* BmpToRgb(unsigned char* input, int width,int hight){
    
    RGB* data = (RGB*)malloc(width*hight*3);
    int y = 0;
    int x = 0;
    memcpy(data,input,width*hight*3);
    for (y = 0; y < hight; y++)
    {
        for (x = 0; x < width; x++)
        {

        // the problem is probably in these 3 lines, if i comment
        // them out no "Segmentation fault (core dumped)" happens.
        data[x+(hight-y)*width].r = input[x+y*width+2];
            
        data[x+(hight-y)*width].g = input[x+y*width];
            
        data[x+(hight-y)*width].b = input[x+y*width+1];

        }
    }
    
    return (unsigned char*)data; 
}

int main(){

    int width;
    int hight;

    unsigned char* imageBMP = ReadBMP("image.bmp",&width,&hight);
    printf("width: %d hight: %d
",width,hight);
    unsigned char* image = BmpToRgb(imageBMP,width,hight);

    free(image);
    printf("freeing
");
    free(imageBMP); // segmentation fault (core dumped) for 1920x1080 images
    printf("done
"); // "done" not printed

    return 0;
}

I want to know why different image resolutions (or maybe it is the file size) may cause a "segmentation fault (core dumped)" or not.

Some extra information that may be relevant:

Operating system : Ubuntu 20.04  
c compiler: gcc
question from:https://stackoverflow.com/questions/65948763/diffent-image-file-size-causes-segmentation-fault-when-memory-is-freed

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

the problem was with these lines

data[x+(hight-y)*width].r = input[x+y*width+2];
            
data[x+(hight-y)*width].g = input[x+y*width];

data[x+(hight-y)*width].b = input[x+y*width+1];

when y = 0 the buffer for data is overrun. This makes the code enter in an undefined behavior state (https://en.cppreference.com/w/c/language/behavior.)

to solve this problem replace the three lines shown above with the following

data[x+(hight-y-1)*width].r = input[x+y*width+2];
            
data[x+(hight-y-1)*width].g = input[x+y*width];

data[x+(hight-y-1)*width].b = input[x+y*width+1];

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...