我怀疑这会影响很多人,因为这相当模糊,但如果你得到你的 FILE* 像这样:
HANDLE hMyFile = CreateFile(...);
FILE* pFile = _fdopen( _open_osfhandle((long)hMyFile, <flags>), "rb" );
CloseHandle(hMyFile);
然后你会为你打开的每个文件泄漏一个流。在执行 _open_osfhandle 和 _fdopen 之后,您必须在 pFile 上调用 fclose() 来关闭您的句柄。 CloseHandle 显然不够聪明,无法释放 fdopen 与您的句柄关联的垃圾,但 fclose 足够聪明,可以关闭您的句柄以及与 FILE* 相关的垃圾。
我正在开发的应用程序这样做是因为某个 API 在 HANDLE 周围传递,并且该 API 的特定实现者需要一个 FILE*,所以实现者做了 _fdopen/_open_osfhandle 的东西来获得一个 FILE*。但是,这意味着调用者的 CloseHandle 调用不足以完全关闭 HANDLE。修复方法是先复制传入的 HANDLE,然后 FILE* 代码可以正确地 fclose() FILE* 而不会破坏调用者的 HANDLE。
示例损坏程序:
#include "stdafx.h"
#include <Windows.h>
#include <io.h>
#include <assert.h>
#include <fcntl.h>
int _tmain(int argc, _TCHAR* argv[])
{
for(int x = 0;x < 1024; x++)
{
HANDLE hFile = CreateFile(L"c:\\temp\\rawdata.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
FILE* pFile = _fdopen( _open_osfhandle((long)hFile, _O_RDONLY | _O_BINARY), "rb" );
assert(pFile); // this assert will go off at x=509, because _getstream() only has 512 streams, and 3 are reserved for stdin/stdout/stderr
CloseHandle(hFile);
}
return 0;
}