找到特定颜色的第一次出现 - 奇怪的分配行为

时间:2014-08-09 22:50:25

标签: c memory-management allocation bmp alloc

我正在编写一个函数,它返回具有指定颜色的第一个定位像素的地址。现在我正在测试检测。目前在50x50 bmp。考虑这段代码:

dword bmp_find_xy (dword xp, dword yp)                                          
{                                                                                                
    dword w = 50;
    word bpx = (3*8);
    dword offset = (2+sizeof(BMP)+sizeof(DIB));
    dword row = (((bpx * w) * 4) / 32);
    dword pixAddress = (offset) + row * yp + ((xp * bpx) / 8);

    return pixAddress;
}                                                                                                

dword bmp_dfind_c (char *FILE_NAME, BYTE R, BYTE G, BYTE B)
{
    dword w = 50;
    dword h = 50;
    dword size;

    int W, H, i;

    FILE* fp = fopen("sample.bmp", "r+b");
    BYTE* bmp;

    fseek(fp, 0L, SEEK_END);
    size = ftell(fp);
    bmp = malloc(size+48); // note this line
    rewind(fp);

    for(i=0; i<size; i++)
    bmp[i] = fgetc(fp);

    fseek(fp, 54, SEEK_SET);

    for(H = h; H >=1; H--)
    {
        for(W = 0; W < w; W++)
        {
            if(bmp[bmp_find_xy(FILE_NAME, W, H)] == 255)
            printf("There is a pix with maxed value");
        }
    }
    fclose(fp);
    return 1;
}

所以..因为即时通讯使用古老的编译器而且没有优化。如果我没有将至少+48的大小放入,我会收到缓冲区溢出的错误。为什么48?如果我只放malloc(size)对我来说没有意义,为什么会溢出呢。

2 个答案:

答案 0 :(得分:3)

您的H循环错误。如果您的图像高100像素,则循环从101到1而不是99到0.因此,bmp_find_xy会计算错误的索引。

尝试用以下代码替换循环:

H = h;
while (h-- > 0) {

这种模式有时被戏称为“转向运营商”。将循环中的无符号变量递减为零是一种安全的方法。

答案 1 :(得分:2)

如果我质疑你的H减量逻辑,请原谅我。假设您的HW从零开始(他们应该是),我相信这一点:

for(H = h; H >=1; H--)

会更好地服务于此:

H = h;
while (H--)

如果真的是后向枚举器H-1打算到0的意图。 (我认为应该是这样)。修复我和我很确定你可以正确分配你的缓冲区。如上所述,期望您在H行搜索,开始循环,并且这样的行不在您的缓冲区中。

如果for循环是强制性的,它实际上涉及更多工作。像这样看似无辜的东西:

for(H=(h-1); H>=0; --H)

无法正常使用作为通用机制。当h和无符号类型开始为0时会发生什么?表达式(h-1)会引入下溢。哎哟。当然,您可以通过执行以下操作来“修复”此问题:

if (h)
{
    for(H=(h-1); H>=0; --H)
    ....
}

但这只是对原本是个坏主意的更多抨击。

以下工作,但相当不太明确imho:

for (H=h; H--;)

这实现了与我们的while循环相同的逻辑,代价是混淆。它带给表的一个(也是唯一的)是local-var-declaration,可以有用:

for (dword var=h; var--;)

有很多方法可以做到这一点,但有一些方法。我发现第一个在你的上下文中最清楚。祝你好运。