无效的投射造成的堆损坏?

时间:2012-12-28 21:15:14

标签: c++ casting heap-corruption

我有代码:

unsigned char *myArray = new unsigned char[40000];

char pixelInfo[3];
int c = 0;
while(!reader.eof()) //reader is a ifstream open to a BMP file
{
    reader.read(pixelInfo, 3);
    myArray[c] = (unsigned char)pixelInfo[0];
    myArray[c + 1] = (unsigned char)pixelInfo[1];
    myArray[c + 2] = (unsigned char)pixelInfo[2];
    c += 3;
}
reader.close();

delete[] myArray; //I get HEAP CORRUPTION here

经过一些测试后,我发现它是由while循环中的强制转换引起的,如果我使用 signed char myArray 我没有得到错误,但我必须使用unsigned char for我的其余代码。 将pixelInfo转换为unsigned char也会产生相同的错误。

有没有解决方案?

3 个答案:

答案 0 :(得分:1)

这是你应该做的:

reader.read((char*)myArray, myArrayLength); /* note, that isn't (sizeof myArray) */

if (!reader) { /* report error */ }

如果循环内部正在进行处理,那么

int c = 0;
while (c + 2 < myArraySize) //reader is a ifstream open to a BMP file
{
    reader.read(pixelInfo, 3);
    myArray[c] = (unsigned char)pixelInfo[0];
    myArray[c + 1] = (unsigned char)pixelInfo[1];
    myArray[c + 2] = (unsigned char)pixelInfo[2];
    c += 3;
}

在你结束之后尝试阅读不是问题 - 你会在阵列的其余部分得到垃圾,但你可以在最后处理它。

假设您的数组足以容纳整个文件,则会导致缓冲区损坏。涉及具有精心设计的错误元数据的图像文件的缓冲区溢出攻击是众所周知的。

不要依赖计算缓冲区大小的整个文件内容。

答案 1 :(得分:0)

reader.eof()只会告诉您上一次读取是否到达文件末尾,这会导致最后一次迭代写入数组末尾。你想要的是检查当前读取是否到达文件末尾。将您的while循环更改为:

while(reader.read(pixelInfo, 3)) //reader is a ifstream open to a BMP file
{
  // ...
}

答案 2 :(得分:0)

请注意,您一次只读取3个字节。如果总字节数不能被3整除(不是3的倍数),那么只有pixelInfo数组的一部分实际上会填充正确的数据,这可能会导致程序出错。您可以尝试以下未测试代码。

while(!reader.eof()) //reader is a ifstream open to a BMP file
{
   reader.read(pixelInfo, 3);
   for (int i = 0; i < reader.gcount(); i++) {
       myArray[c+i] = pixelInfo[i];
   }
   c += 3;
}

您的代码确实遵循cplusplus.com上的文档,因为eof位将在读取不完整后设置,因此此代码将在您上次阅读后终止,但正如我之前提到的,您的问题的可能原因是您正在将可能的垃圾数据分配给堆,因为如果未读取3个字节,则可能不一定会设置pixelInfo [x]。