Я сомневаюсь, что это затронет многих людей, так как это довольно неясно, но если вы получите свой ФАЙЛ *, как это:
HANDLE hMyFile = CreateFile(...);
FILE* pFile = _fdopen( _open_osfhandle((long)hMyFile, <flags>), "rb" );
CloseHandle(hMyFile);
Тогда вы будете пропускать поток для каждого файла, который вы открываете. После выполнения _open_osfhandle и _fdopen вы должны вызвать fclose () для pFile, чтобы закрыть свой дескриптор. Очевидно, что CloseHandle недостаточно умен, чтобы освободить крошку, которую fdopen ассоциирует с вашей ручкой, но fclose достаточно умен, чтобы закрыть вашу ручку вместе с флайтом * связанным с фрейтом.
Приложение, над которым я работал, делало это, потому что определенный 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;
}