我正在编写一个函数,它返回具有指定颜色的第一个定位像素的地址。现在我正在测试检测。目前在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)
对我来说没有意义,为什么会溢出呢。
答案 0 :(得分:3)
您的H
循环错误。如果您的图像高100像素,则循环从101到1而不是99到0.因此,bmp_find_xy会计算错误的索引。
尝试用以下代码替换循环:
H = h;
while (h-- > 0) {
这种模式有时被戏称为“转向运营商”。将循环中的无符号变量递减为零是一种安全的方法。
答案 1 :(得分:2)
如果我质疑你的H减量逻辑,请原谅我。假设您的H
和W
从零开始(他们应该是),我相信这一点:
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--;)
有很多方法可以做到这一点,但有一些方法。我发现第一个在你的上下文中最清楚。祝你好运。