Странное поведение printf после вызова fread

Я пытаюсь разработать функцию, которая будет загружать растровые изображения в память и в конечном итоге отображать ее. Я компилирую код с помощью 16-битного C-компилятора Watcom с целью, установленной на DOS. Я запускаю программу в DOSBox. Код выглядит следующим образом:

#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

Когда вы запустите эту программу, она выдаст: "BMP width: %dpx\n", но ничего после символа новой строки?? Я нахожу это чрезвычайно странным. Я подтвердил, что ни одна из операций не завершилась неудачно, и не установил значение errno, и что px_height на самом деле имеет соответствующее значение. У кого-нибудь из вас есть опыт?

2 ответа

Решение

У вас только маллок достаточно места для указателя с этой строкой

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

что вам действительно нужно

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

Кроме того, как отметил mrbatch, вы используете 16-битный компилятор и пытаетесь прочитать 4 байта данных в 2 байта. int переменные. Убедитесь, что sizeof() ваших типов соответствует тому, что вы читаете, например long int

Так что, в общем, вы портите свой стек и кучу, записывая больше данных, чем должны, и вы можете ожидать, что ваша программа будет вести себя очень странно:)

В дополнение к ответу Павла, чтобы исправить sizeof для тебя malloc попробуйте поменять int значения для long в их объявлении (я предполагаю, что ваш код верен в отношении растрового изображения, содержащего 4-байтовые значения для чтения). int в 16-битном компиляторе будет 2 байта. Тебе необходимо long (или эквивалентно long int) для 4-байтового значения.


Как предлагается в комментариях, еще лучше было бы включить inttypes.h и использовать int32_t вместо int или же long чтобы обеспечить 32-битное значение.

Другие вопросы по тегам