堆损坏和随机断点
Heap corruption and random breakpoints
我正在尝试完成我的简单存档系统。我使用 MFC 应用程序来处理构建存档文件。唯一的问题是一个函数似乎会导致错误,但 Visual Studio 无法告诉我错误的位置或原因,所以我不知道该怎么做。即使在搜索之后,none 的解决方案对我有用。
bool UE_ArchiveLoad(UE_Archive * archive, char* path)
{
ifstream input = ifstream(path, std::ifstream::in | std::ifstream::ate | std::ifstream::binary);
char* Header = new char[3];
char version = 0;
if (input.fail())
{
return false;
}
input.seekg(0, ios::beg);
input.read(Header, 3);
input.read(&version, 1);
string T = Header;
T = T.substr(0, 3);
Header = (char*)T.c_str();
if (strcmp( Header,UE_ARCHIVE_SIGNATURE)!=0)
{
printf("INVALID SIGNATURE: ");
cout << Header <<endl ;
return false;
}
if (version != UE_ARCHIVE_VERSION)
{
printf("INVALID VERSION");
return false;
}
archive->Header = UE_ArchiveHeader();
archive->Header.signature = Header;
archive->Header.version = version;
while(input.is_open())
{
auto F = make_unique<UE_ArchiveFile>();
auto Name = std::make_unique<char>();
input.read(Name.get(), 128);
F->name = Name.get();
input.read(reinterpret_cast<char*>(&F->size), sizeof(long));
if (F->size < 0)
break;
char * buffer = new char[F->size];
input.read(buffer, F->size);
F->buffer = buffer;
if (input.fail())
{
break;
}
else
archive->Files.push_back(move(F));
}
input.close();
return true;
}
有时这个函数运行时不会自动触发断点,但如果它起作用,那么在使用这个函数后,程序会在闲置几秒钟后随机断点。其他时候它会停在最后一行。我无法弄清楚有这么多不一致是怎么回事,我知道我在这里做了一些事情来破坏程序。
很可能是由于您的使用方式 Header
。
首先你动态分配三个字节。然后你读了三个字节。没关系。然后你将它分配给一个字符串。不好。没有终止 nul,因此它将继续读取内存,直到找到一个并导致未定义的行为。
整个事情一团糟。为什么要遍历字符串?你清楚地意识到出了问题并试图修复它。
你也将泄漏内存,因为你不释放分配。
为什么不分配一个四字节数组,读取三个字节并将第四个字节设置为 nul?那么你就不需要整个字符串 kludge 并且可能不会有随机崩溃。
此外,由于 archive
在外部使用,您还有另一个问题:您正在存储对本地对象的引用,该对象将在方法完成后被销毁,从而导致更多问题。
并且在提前返回的情况下释放内存。
我正在尝试完成我的简单存档系统。我使用 MFC 应用程序来处理构建存档文件。唯一的问题是一个函数似乎会导致错误,但 Visual Studio 无法告诉我错误的位置或原因,所以我不知道该怎么做。即使在搜索之后,none 的解决方案对我有用。
bool UE_ArchiveLoad(UE_Archive * archive, char* path)
{
ifstream input = ifstream(path, std::ifstream::in | std::ifstream::ate | std::ifstream::binary);
char* Header = new char[3];
char version = 0;
if (input.fail())
{
return false;
}
input.seekg(0, ios::beg);
input.read(Header, 3);
input.read(&version, 1);
string T = Header;
T = T.substr(0, 3);
Header = (char*)T.c_str();
if (strcmp( Header,UE_ARCHIVE_SIGNATURE)!=0)
{
printf("INVALID SIGNATURE: ");
cout << Header <<endl ;
return false;
}
if (version != UE_ARCHIVE_VERSION)
{
printf("INVALID VERSION");
return false;
}
archive->Header = UE_ArchiveHeader();
archive->Header.signature = Header;
archive->Header.version = version;
while(input.is_open())
{
auto F = make_unique<UE_ArchiveFile>();
auto Name = std::make_unique<char>();
input.read(Name.get(), 128);
F->name = Name.get();
input.read(reinterpret_cast<char*>(&F->size), sizeof(long));
if (F->size < 0)
break;
char * buffer = new char[F->size];
input.read(buffer, F->size);
F->buffer = buffer;
if (input.fail())
{
break;
}
else
archive->Files.push_back(move(F));
}
input.close();
return true;
}
有时这个函数运行时不会自动触发断点,但如果它起作用,那么在使用这个函数后,程序会在闲置几秒钟后随机断点。其他时候它会停在最后一行。我无法弄清楚有这么多不一致是怎么回事,我知道我在这里做了一些事情来破坏程序。
很可能是由于您的使用方式 Header
。
首先你动态分配三个字节。然后你读了三个字节。没关系。然后你将它分配给一个字符串。不好。没有终止 nul,因此它将继续读取内存,直到找到一个并导致未定义的行为。
整个事情一团糟。为什么要遍历字符串?你清楚地意识到出了问题并试图修复它。
你也将泄漏内存,因为你不释放分配。
为什么不分配一个四字节数组,读取三个字节并将第四个字节设置为 nul?那么你就不需要整个字符串 kludge 并且可能不会有随机崩溃。
此外,由于 archive
在外部使用,您还有另一个问题:您正在存储对本地对象的引用,该对象将在方法完成后被销毁,从而导致更多问题。
并且在提前返回的情况下释放内存。