【发布时间】:2021-08-03 02:26:19
【问题描述】:
我目前正在尝试实现一个将多个文件加载到内存中以进行进一步处理的程序。为了查看文件是否存在,我创建了一个使用 GetFileAttributesW 来检查文件是否确实存在的函数。
第一个文件被正确加载,但是一旦我尝试加载第二个文件,我就会遇到访问冲突(GetLastError 返回 8;ERROR_NOT_ENOUGH_MEMORY)。我可以安全地排除我没有足够的 RAM,因为文件是最大的。 500kb 大小,我从不加载超过 20 个(我有 16GB 的 RAM)。 我也有权访问他的文件等。
inline BOOL FileExists(const TCHAR* szPath)
{
DWORD dwAttrib = GetFileAttributesW(szPath); // ERROR here (1st iteration everything is fine)
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
.
.
.
FILE_DATA LoadFileIntoMemory(const TCHAR* FileName)
{
PTCHAR FinalPath = VirtualAlloc(NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
PTCHAR FilePath = L"C:\\Users\\invasi0nZ\\"; //
concat(FinalPath, FilePath, MAX_PATH);
concat(FinalPath, FileName, MAX_PATH);
if (!FileExists(FinalPath))
{
memset(FinalPath, 0, MAX_PATH);
FilePath = L"C:\\Users\\invasi0nZ\\Documents\\";
concat(FinalPath, FilePath, MAX_PATH);
concat(FinalPath, FileName, MAX_PATH);
}
HANDLE File = CreateFileW(FinalPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (File == INVALID_HANDLE_VALUE)
{
return (FILE_DATA){ NULL, NULL };
}
int FileSize = GetFileSize(File, NULL);
PBYTE RawFile = VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
DWORD dwRead;
size_t FileSize = GetFileSize(File, NULL);
ReadFile(File, RawFile, FileSize, &dwRead, NULL);
CloseHandle(File);
VirtualFree(FinalPath, sizeof(FinalPath), MEM_FREE);
return (FILE_DATA) { RawFile, FileSize };
}
.
.
.
void LoadAllFiles(Array FileNames)
{
for (int i = 0; i < FileNames.used; i++)
{
FILE_DATA file_data = LoadFileIntoMemory(FileNames.array[i].file_name);
// Store file_data, etc.
}
// Do stuff with files here
}
据我所知,我正在关闭所有必需的句柄并在不破坏程序的情况下释放所有可能的东西。
非常感谢您!
【问题讨论】:
-
那么,C++ 标签在这里做什么?如果这不是 C++ 问题,请不要这样标记。
-
请显示完整的错误诊断,未删节。当您遇到访问冲突时,调用
GetLastError毫无意义。 -
您到底为什么要使用
VirtualAlloc作为通用分配器?如果您想要纯 WinAPI,请使用HeapAlloc或GlobalAlloc用于通用用途,SysAllocString用于宽字符串。 -
在您的固定大小分配的超级特定情况下,只需执行
WCHAR FinalPath[MAX_PATH + 1]; -
要修复您的错误,请使用调试器,在
GetFileAttributesW调用上设置断点,并检查调用前立即存在的值。