C++ 无效强制转换导致堆损坏?

C++ 无效强制转换导致堆损坏?,c++,casting,heap-corruption,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 *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循环中的强制转换引起的,如果我使用有符号字符myArray我不会得到错误,但我必须在我的其余代码中使用无符号字符。 将pixelInfo强制转换为无符号字符也会产生相同的错误

有什么解决方案吗?

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

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

这就是你应该做的:

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;
}
intc=0;
而(c+2
在到达末尾后尝试阅读不是问题——在数组的其余部分中会出现垃圾,但在结尾时可以处理这些问题

假设数组足够大,可以容纳整个文件,则会导致缓冲区损坏。众所周知,使用精心编制的不正确元数据的图像文件进行缓冲区溢出攻击


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

请注意,一次读取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;
}
while(!reader.eof())//reader是打开BMP文件的ifstream
{
reader.read(pixelInfo,3);
for(int i=0;i

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

的诅咒!eof()
条件返回。您确定没有写入数组的边界吗?好的,您就是豚鼠。你能告诉我们你为什么这么想吗!reader.eof()
是一个合理的条件吗?请详细解释你的推理,或你的信息来源。似乎每一个涉足C++的人都会犯错误,我真的很想知道这个普遍的误解来自哪里。(1)检查<代码>读取器.EFF()>代码>是检测流的结尾的一种很差的方法(2)流的结尾不是开始的正确终止条件——读取预期的像素数目,ISI没有太多的C++经验,并且我一直在阅读的关于BMP文件的所有教程都是这样的,所以我只是继续…myArray并不是固定在40000,我写过为了更容易阅读,我在读取文件头后得到了数组边界,所以我会将它更改为预期的像素数,它实际上更符合逻辑。谢谢。不,“检查当前读取是否到达文件末尾”根本不是他想要的。当他到达像素阵列的末端时停止是他所需要的。代码示例对我不起作用,因为我编写了一个简化版本,我实际上在循环过程中在这里和那里更改了一个值。但是非常感谢关于缓冲区溢出的信息,我要做一些事情使它更安全。@Danicco:那么,你可以在(c时将循环写成
。重要的是,I/O错误会产生垃圾结果,但不会导致崩溃。另一方面,溢出阵列是一种崩溃,甚至更糟,是一种安全漏洞。所以我知道循环需要检查哪种情况。这就是我所做的,它现在工作得非常好,也感谢您提供的额外信息!仍然滥用
eof()
,仍然愉快地溢出数组并破坏堆。@Ben Voigt我不确定我是如何滥用eof的。它检查是否设置了在发生故障时读取的位。在未完成读取的情况下,数组仍将被分配,并将在下一次迭代中退出。如果阵列读取完最后3个字节,那么下一次迭代将尝试读取另外3个字节,它将失败并导致下一次eof检查失败。要回答我自己的问题: