问题解决了,谢谢大家的帮助
我在这里遇到了一些问题,这并没有让我的程序爆炸,但是我无法解决这个问题。我有一个函数读取文件中的一些数据,在执行结束时,变量longGarbage周围的堆栈已损坏。我看了一下,发现可能的原因是写入无效的内存。我清理了一些内存泄漏,问题仍然存在。令我感到困惑的是,当函数完成执行时会发生这种情况,因此当变量超出范围时,它似乎正在发生。这是代码......
CHCF::CHCF(std::string fileName)
: PAKID("HVST84838672")
{
FILE * archive = fopen(fileName.c_str(), "rb");
std::string strGarbage = "";
unsigned int intGarbage = 0;
unsigned long longGarbage = 0;
unsigned char * data = 0;
char charGarbage = '0';
if (!archive)
{
fclose (archive);
return;
}
for (int i = 0; i < 12; i++)
{
fread(&charGarbage, 1, 1, archive);
strGarbage += charGarbage;
}
if (strGarbage != PAKID)
{
fclose(archive);
throw "Incorrect archive format";
}
strGarbage = "";
fread(&_gameID, sizeof(_gameID),1,archive);
fread(&_fileCount, sizeof(_fileCount),1,archive);
for (int i = 0; i < _fileCount; i++)
{
fread(&longGarbage, 8,1,archive); //file offset
fread(&intGarbage, 4, 1, archive);//fileName
for (int i = 0; i < intGarbage; i++)
{
fread(&charGarbage, 1, 1, archive);
strGarbage += charGarbage;
}
fread(&longGarbage, 8, 1, archive); //fileSize
fread(&intGarbage, 4, 1, archive); //fileType
data = new unsigned char[longGarbage];
for (long i = 0; i < longGarbage; i++)
{
fread(&charGarbage, 1, 1, archive);
data[i] = charGarbage;
}
switch ((FILETYPES)intGarbage)
{
case MAP:
_maps.append(strGarbage, new CFileData(strGarbage, FILETYPES::MAP, data, longGarbage));
break;
default:
break;
}
delete [] data;
data = 0;
strGarbage.clear();
longGarbage = 0;
}
fclose(archive);
} //error happens here
这是CFileData构造函数:
CFileData::CFileData(std::string fileName, FILETYPES type, unsigned char *data, long fileSize)
{
_fileName = fileName;
_type = type;
_data = new unsigned char[fileSize];
for (int i = 0; i < fileSize; i++)
_data[i] = data[i];
}
答案 0 :(得分:2)
我可以建议std::vector
而不是手动调用new和delete吗?您的代码不是异常安全的 - 如果抛出异常,则会泄漏。
fread(&longGarbage, 8, 1, archive); //fileSize
您确定sizeof(long)
是8吗?我怀疑它是4.我相信Linux机器有时它是8,但大多数其他地方sizeof(long)
是4,而sizeof(long long)
是8。
这个班级成员的任何构造者怎么样?它们也可以破坏堆栈。
答案 1 :(得分:1)
正在发生的事情是写入longGarbage周围或之上的内存,这会导致损坏。
您没有说明您正在使用的开发环境。诊断此问题的一种方法是设置在特定内存位置更改时触发的断点。选择与损坏区域重叠的内存位置,并等待它意外触发。
另一种诊断方法是检查改变longGarbage周围或之上的内存的代码。当然,这几乎可以是任何事情,但可能的候选者是对“数据”的修改,对“intGarbage”的修改以及对“longGarbage”本身的修改。
我们可以进一步缩小范围,因为我们可以(通常)相当确定赋值运算符本身是安全的。像data = new...
这样的代码不太可能是罪魁祸首所以我们真的需要关注涉及获取“数据”,“intGarbage”或“longGarbage”地址的内存更改。特别是内存更改会改变更多的字节数。
其他几个人已经指出长度可能不是8个字节。如果你将错误的长度传递给fread,则检索到的额外字节必须在某处。
答案 2 :(得分:0)
你正在使用大量的魔术数字来表示数据大小,所以我先检查一下。特别是,我怀疑sizeof(unsigned long)==8
和sizeof(unsigned in)==4
在所有可能的情况下。请参阅编译器的文档,但您仍应保持警惕,因为这很可能会从一个编译器/平台更改为另一个编译器/平台。
检查这些位:
fread(&longGarbage, 8,1,archive); //file offset
您也可能希望使用C ++ <iostream>
库而不是C FILE*
内容进行阅读。它将允许更短的版本,因为您不需要关闭文件3次。
答案 3 :(得分:0)
从其他评论和提供的信息看来,问题出在C ++方面,你应该使用__int64用于windows环境,或者int64_t用于跨平台。