C GetFileAttributesW导致访问冲突读取位置x(GetLastError返回8)
我目前正在尝试实现一个程序,将多个文件加载到内存中,以便进一步处理。为了查看文件是否存在,我创建了一个函数,使用GetFileAttributesW检查文件是否确实存在 第一个文件被正确加载,但一旦我尝试加载第二个文件,就会出现访问冲突(GetLastError返回8;ERROR\u内存不足)。我可以安全地排除我没有足够的RAM的可能性,因为文件的最大大小为500kb,而且我从来没有加载超过20个(我有16GB的RAM)。 我也有权访问he文件等C GetFileAttributesW导致访问冲突读取位置x(GetLastError返回8),c,winapi,C,Winapi,我目前正在尝试实现一个程序,将多个文件加载到内存中,以便进一步处理。为了查看文件是否存在,我创建了一个函数,使用GetFileAttributesW检查文件是否确实存在 第一个文件被正确加载,但一旦我尝试加载第二个文件,就会出现访问冲突(GetLastError返回8;ERROR\u内存不足)。我可以安全地排除我没有足够的RAM的可能性,因为文件的最大大小为500kb,而且我从来没有加载超过20个(我有16GB的RAM)。 我也有权访问he文件等 inline BOOL FileExists(c
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
}
inline BOOL文件存在(const TCHAR*szPath)
{
DWORD dwAttrib=GetFileAttributesW(szPath);//此处出错(第一次迭代一切正常)
返回(dwAttrib!=无效的文件属性&&!(dwAttrib&FILE属性目录));
}
.
.
.
文件\数据加载FileInMemory(常量TCHAR*文件名)
{
PTCHAR FinalPath=VirtualAlloc(NULL,MAX_PATH,MEM_COMMIT,MEM_RESERVE,PAGE_READWRITE);
PTCHAR FilePath=L“C:\\Users\\invasi0nZ\\”;//
concat(最终路径、文件路径、最大路径);
concat(最终路径、文件名、最大路径);
如果(!FileExists(FinalPath))
{
memset(最终路径,0,最大路径);
FilePath=L“C:\\Users\\invasi0nZ\\Documents\\”;
concat(最终路径、文件路径、最大路径);
concat(最终路径、文件名、最大路径);
}
HANDLE File=CreateFileW(FinalPath,GENERIC_READ,File_SHARE_READ,NULL,OPEN_EXISTING,File_ATTRIBUTE_NORMAL,NULL);
if(File==无效的\u句柄\u值)
{
返回(文件数据){NULL,NULL};
}
int FileSize=GetFileSize(文件,NULL);
PBYTE RawFile=VirtualAlloc(NULL,FileSize,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
德沃德·德雷德;
size\u t FileSize=GetFileSize(文件,NULL);
ReadFile(File,RawFile,FileSize,&dwRead,NULL);
关闭句柄(文件);
VirtualFree(FinalPath、sizeof(FinalPath)、MEM_FREE);
返回(文件\数据){RawFile,FileSize};
}
.
.
.
void LoadAllFiles(数组文件名)
{
for(int i=0;i
就我所见,我正在关闭所有必需的句柄,并在不破坏程序的情况下释放所有可以释放的内容
提前非常感谢 您没有使用
VirtualAlloc()
分配足够的内存,因此concat()
函数可能导致缓冲区溢出。由于编译时启用了UNICODE
,TCHAR
是wchar\t
,大小为2个字节。在为FinalPath
分配内存时,以及使用memset()
清除FinalPath
时,需要考虑该大小
更改此项:
PTCHAR FinalPath = VirtualAlloc(NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
...
memset(FinalPath, 0, MAX_PATH);
为此:
PTCHAR FinalPath = VirtualAlloc(NULL, sizeof(TCHAR) * MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
...
memset(FinalPath, 0, sizeof(TCHAR) * MAX_PATH);
您的代码也存在其他问题。在使用返回的指针之前,您不会检查VirtualAlloc()
是否成功。如果CreateFileW()
失败,则正在泄漏分配的内存。并且您两次声明FileSize
请尝试以下方法:
FILE\u数据加载fileinto内存(const TCHAR*FileName)
{
PTCHAR FinalPath=VirtualAlloc(NULL,sizeof(TCHAR)*最大路径,MEM_COMMIT,MEM_RESERVE,PAGE_READWRITE);
如果(!FinalPath)
返回(文件数据){NULL,0};
PTCHAR FilePath=TEXT(“C:\\Users\\invasi0nZ\\”;//
concat(最终路径、文件路径、最大路径);
concat(最终路径、文件名、最大路径);
如果(!FileExists(FinalPath))
{
memset(FinalPath,0,sizeof(TCHAR)*最大路径);
FilePath=TEXT(“C:\\Users\\invasi0nZ\\Documents\\”;
concat(最终路径、文件路径、最大路径);
concat(最终路径、文件名、最大路径);
}
HANDLE File=CreateFile(FinalPath,GENERIC\u READ,File\u SHARE\u READ,NULL,OPEN\u EXISTING,File\u ATTRIBUTE\u NORMAL,NULL);
if(File==无效的\u句柄\u值)
{
VirtualFree(最终路径,0,MEM_发布);
返回(文件数据){NULL,0};
}
VirtualFree(最终路径,0,MEM_发布);
DWORD FileSize=GetFileSize(文件,NULL);
if(FileSize==无效的文件大小)
{
关闭句柄(文件);
返回(文件数据){NULL,0};
}
PBYTE RawFile=VirtualAlloc(NULL,FileSize,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
如果(!RawFile)
{
关闭句柄(文件);
返回(文件数据){NULL,0};
}
德沃德·德雷德;
if(!ReadFile(File,RawFile,FileSize,&dwRead,NULL))
{
VirtualFree(RawFile,0,MEM_发行版);
RawFile=NULL;
dwRead=0;
}
关闭句柄(文件);
返回(文件\数据){RawFile,dwRead};
}
也就是说,您根本不需要FileExists()
,因为CreateFile()
可以告诉您该文件是否存在,从而避免在您检查文件是否存在后但在您打开该文件之前,如果另一个进程创建/删除该文件,则代码中会出现争用情况
您还应该摆脱VirtualAlloc()
对于FinalPath
,您不需要动态分配该字符串。只需静态声明数组即可
Win32 API具有将路径段连接在一起的函数,因此您无需编写自己的函数。它还具有查询用户配置文件和文档文件夹路径的功能,您不应该硬编码这些路径
请尝试类似以下内容:
#包括
#包括
#包括
句柄OpenFileInFolder(CSIDL FolderID,const TCHAR*文件名)
{
TCHAR文件路径[最大路径];
HRESULT Res=SHGetFolderPath(NULL,FolderID,NULL,SHGFP\u TYPE\u CURRENT,FilePath);
如果(Res!=S_OK)
{
SetLastError(Res);
返回无效的\u句柄\u值;
}
Res=路径组合(文件路径、最大路径、文件路径、文件名);
如果(Res!=S_OK)
{
塞特拉斯特罗