认为这可能对某人有帮助,因为这对我来说是一种惊喜。
WriteFile 函数尝试写入其第 4 个(可选)参数,如果它为 NULL,则会导致访问冲突异常......但在 Windows 8(.1) 上不会。
这是来自msdn的函数定义:
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten, // Optional
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
lpNumberOfBytesWritten [out, optional] ... 只有当 lpOverlapped 参数不为 NULL 时,此参数才能为 NULL。
我创建了重现错误的简短示例。代码是在 Visual Studio 2008 SP1 中创建的 Win32 控制台应用程序:
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = CreateFile(L"N:\\Test\\Test.tmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
if (INVALID_HANDLE_VALUE == hFile) {
return -1;
}
unsigned int testValue = 32;
//-----------------------------------------------
// Next line generates AV exception on Windows 7,
// On Windows 8 it works fine:
//-----------------------------------------------
WriteFile(hFile, &testValue, sizeof(unsigned int), NULL, NULL);
CloseHandle(hFile);
return 0;
}
最后,如果我通过以下两行更改对 WriteFile() 的调用,则可以解决问题并适用于所有平台:
// Now it does not generate AV:
DWORD written = 0;
WriteFile(hFile, &testValue, sizeof(unsigned int), &written, NULL);
该代码在 Windows 7 和 Windows XP SP3 上生成访问冲突(未在 Vista 上测试)。在 Windows 8(.1) 上它可以工作,即使我在第四个参数 (lpNumberOfBytesWritten) 中传递了 NULL。
实际的问题是我开发了一个写入临时文件的模块,但我忽略了第四个参数(我读了“可选”但误读了其余的并认为它可能被忽略了)。我在 Windows 8.1 上开发并测试了它,所以代码运行良好,但是客户端机器在 Windows 7 上并且代码失败。
我学到的教训:我应该更加专注(注意细节),不要沾沾自喜(仔细测试)。