首页 > fread奇怪的副作用

fread奇怪的副作用

我写了一个函数,用于从HZK16字库中提取字模:

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

uint16_t *
get_bitmap_font(long offset, const unsigned char *str, uint16_t *data)
{
    unsigned offset_size = 16 * 16 / 8;

    unsigned code_point = (str[0] - 0xA1) * 94 + (str[1] - 0xA1);

    if (str[0] >= 0xA1) {
        offset += code_point * offset_size;
    } else {
        offset += (str[0] + 156 - 1) * offset_size;
    }
    FILE *fp = fopen("HZK16", "rb");
    fseek(fp, offset, SEEK_SET);

    
    printf("before fread: 0x%x 0x%x\n", str[0], str[1]);
    /* 比方说,我提供的参数 str 是一个 GB2312 字符“金” */
    /* 那么此处输出就是对应的编码:0xbd 0xf0 */
    
    fread(data, sizeof(*data), offset_size, fp);
    
    printf(" after fread: 0x%x 0x%x\n", str[0], str[1]);
    /* 输出居然变成了 0x0 0x1 */
    
    
    fclose(fp);
    fp = NULL;
    return data;
}

int
main(void)
{
    unsigned char *str = "\xbd\xf0";
    uint16_t font_data[16];

    get_bitmap_font(0, str, font_data);
    for (int row = 0; row < 16; row++) {
        for (int col = 7; col >= 0; col--) {
            fputs(((font_data[row] >> col) & 1)? "@@": "  ", stdout);
        }
        for (int col = 15; col >= 8; col--) {
            fputs(((font_data[row] >> col) & 1)? "%%": "  ", stdout);
        }
        putchar('\n');
    }
}

    return 0;
}

运行之后,发现这个函数的行为和预期的不同。在检查的过程中,加上了上面的两个printf,发现fread前后str指向的内容居然变了!

但是fread的调用当中并未提到str啊?求解释…

附上点阵字体:
https://github.com/aguegu/BitmapFont/blob/master/font/HZK16


get_bitmap_font 是如何调用的?

你向 data 指向的空间写了64个bytes, 是否溢出? data如果没有64, 且 str的空间和 data在一起(比如都在上一层栈中), 那么就把 str 复写了.


终于明白问题出在哪了。fread的参数offset应当改为offset / sizeof uint16_t。

【热门文章】
【热门文章】