Search code examples
cbitmapdosbmpwatcom

Odd printf behaviour after calling fread


I am trying to devise a function that will load bitmap images into memory and ultimately display it. I am compiling the code with Watcom 16-bit C compiler with the target set to DOS. I am running the program in DOSBox. The code is as follows:

#ifndef __BITMAP_H__
#define __BITMAP_H__

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

typedef struct DIB
{
    int header_size;
    int px_width;
    int px_height;
}DIB_t;

DIB_t *load_bitmap(char *file_name)
{
    FILE *bmp_file;
    DIB_t *bitmap;
    char garbage[4];
    int c, file_size, pixel_offset;

    bitmap = (DIB_t*)malloc(sizeof bitmap);

    if(!bitmap)
    {
        perror("malloc()");
        return NULL;
    }

    bmp_file = fopen(file_name, "rb");

    if(!bmp_file)
    {
        perror("fopen()");
        return NULL;
    }

    c = fgetc(bmp_file);

    if(c == 'B')
    {
        c = fgetc(bmp_file);

        if(c == 'M')
        {
            fread(&file_size, 4, 1, bmp_file);
            fread(garbage, 1, 4, bmp_file);
            fread(&pixel_offset, 4, 1, bmp_file);
            fread(&bitmap->header_size, 4, 1, bmp_file);
            fread(&bitmap->px_width, 4, 1, bmp_file);
            fread(&bitmap->px_height, 4, 1, bmp_file);
            printf("BMP width: %dpx\nBMP Height: %dpx", bitmap->px_width, bitmap->px_height);
            fclose(bmp_file);
            return bitmap;
        }
    }

    fputs("File format not supported.\n", stderr);
    fclose(bmp_file);
    return NULL;
}
#endif

When you run this program it will output: "BMP width: %dpx\n" but nothing after the newline character?? I find this extremely odd. I have confirmed that none of the operations fail or set the errno and that px_height is actually set to it's appropiate value. Is this something any of you have experience with?


Solution

  • You're only malloc'ing enough space for a pointer with this line

    bitmap = (DIB_t*)malloc(sizeof(bitmap));
    

    what you really need is

    bitmap = (DIB_t*)malloc(sizeof(DIB_t));
    

    Also, as mrbatch noted, you're using a 16 bit compiler and so attempting to read 4 bytes of data into 2 byte int variables. Make sure the sizeof() your types matches what you're reading, e.g. a long int

    So - in general - you are corrupting both your stack and your heap by writing more data than you should, and you can expect your program to behave very oddly :)