我有一个在Visual Studio调试环境(包含Debug和Release配置)内部运行时工作正常的函数,但在IDE中运行外部的应用程序时,就像结束一样 - 用户会这样做,程序崩溃了。调试和发布版本都会发生这种情况。
我知道Debug和Release配置(优化,调试符号等)之间可能存在的差异,并且至少在某种程度上意识到在Visual Studio中运行应用程序与在其外部运行应用程序之间的差异(调试堆,工作目录等)。我看过其中的几件事似乎都没有解决这个问题。这实际上是我第一次发布到SO;通常我可以从现有职位找到解决方案,所以我真的很难过!
我能够附加一个调试器,奇怪的是我得到两个不同的错误消息,这取决于我是否在Windows 7上运行应用程序而不是Windows 8.1。对于Windows 7,错误只是一个访问冲突,它在return语句中正确。对于Windows 8.1,它是一个堆损坏错误,它打破了std :: ifstream的构造。在这两种情况下,所有局部变量都被正确填充,因此我知道这不是函数无法找到文件或将其内容读入缓冲区数据的问题。
同样有趣的是,这个问题在Windows 8.1上只有20%的时间发生,在Windows 7上只有100%的时间发生,尽管这可能与这些操作系统正在运行的各种硬件有关。
我不确定它有什么不同,但项目类型是Win32桌面应用程序,它初始化DirectX 11.你会注意到文件类型被解释为二进制,这是正确的,因为这个函数主要是加载编译着色器。
这是静态成员函数 LoadFile :
HRESULT MyClass::LoadFile(_In_ const CHAR* filename, _Out_ BYTE** data, _Out_ SIZE_T* length)
{
CHAR pwd[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, pwd);
std::string fullFilePath = std::string(pwd) + "\\" + filename;
std::ifstream file(fullFilePath, std::ifstream::binary);
if (file)
{
file.seekg(0, file.end);
*length = (SIZE_T)file.tellg();
file.seekg(0, file.beg);
*data = new BYTE[*length];
file.read(reinterpret_cast<CHAR*>(*data), *length);
if (file) return S_OK;
}
return E_FAIL;
}
更新
有趣的是,如果我在堆上分配std :: ifstream 文件并且不删除它,问题就会消失。在我的案例中,必须有一些关于导致问题的ifstream的破坏。
答案 0 :(得分:0)
您没有检查GetCurrentDirectoryA的返回值 - 也许您当前的目录名太长或者什么?
如果您已经在使用Win32(不可移植!),请使用GetFileSize获取文件大小而不是进行搜索
更好的是,使用boost编写可移植代码
启用编译器选项中的所有警告
启用ios例外
答案 1 :(得分:0)
好吧,我放弃尝试使用ifstream。显然,我并不是唯一一个有这个问题的人...只是搜索&#34; ifstream析构函数崩溃&#34;。
由于此应用程序基于DirectX并且只能在Windows上运行,因此我使用了Windows API路由,一切运行正常。
工作代码,万一有人关心:
HRESULT MyClass::LoadFile(_In_ const CHAR* filename, _Out_ BYTE** data, _Out_ SIZE_T* length)
{
CHAR pwd[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, pwd);
string fullFilePath = string(pwd) + "\\" + filename;
WIN32_FIND_DATAA fileData;
HANDLE file = FindFirstFileA(fullFilePath.c_str(), &fileData);
if (file == INVALID_HANDLE_VALUE) return E_FAIL;
file = CreateFileA(fullFilePath.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (file == INVALID_HANDLE_VALUE) return E_FAIL;
*length = (SIZE_T)fileData.nFileSizeLow;
*data = new BYTE[*length];
DWORD bytesRead;
if (ReadFile(file, *data, *length, &bytesRead, NULL) == FALSE || bytesRead != *length)
{
delete[] *data;
*length = 0;
CloseHandle(file);
return E_FAIL;
}
CloseHandle(file);
return S_OK;
}