异步 ReadFile() 导致 运行 时间错误?

Asynchronous ReadFile() causing run-time errors?

我正在实现一个读取子进程输出的函数。我的程序一般是单线程的,我只用异步的API来实现读取超时(同步版本的ReadFile()不可用)。我创建了一个 OVERLAPPED 结构,调用异步 ReadFile() 然后 WaitForSingleObject() 具有所需的超时时间。

读取函数完成后,MSVC 有时会报告:

Run-Time Check Failure #2 - Stack around the variable 'rdCount' was corrupted.

我尝试了各种调试和修复它的方法。报告的变量只是函数中声明的最后一个变量。根据内存查看,函数WaitForSingleObject()有时会出现写入三个DWORD,其中最后一个与rdCount重叠,然后报告损坏。

… cc cc cc cc 00 00 00 00 00 00 00 00 0f 00 00 00 cc cc cc cc …
                                      └ rdCount ┘

否则它只写入这些 DWORD 中的第一个,然后函数正确完成。

… cc cc cc cc 02 01 00 00 cc cc cc cc 00 00 00 00 cc cc cc cc …
                                      └ rdCount ┘

有趣的是,当我添加一些大小至少为 48 字节的填充(参见 padding 数组)时,问题消失了,因为 00 00 00 00 0f 00 00 00 的写入发生在该数组中。

谁能解释一下?我是不是遗漏了什么或者 WinAPI 有什么问题?

函数主体如下(删除了日志记录和检查)。

HANDLE readFinishEvent = CreateEvent(
                           NULL,   // default security attributes
                           TRUE,   // manual-reset event
                           FALSE,  // initial state is nonsignaled
                           NULL    // unnamed
                           );
QByteArray response;
CHAR buffer[BufferSize];
OVERLAPPED ovl;
CHAR padding[48]; // <----------- ARTIFICIAL PADDING -----------
ZeroMemory(&ovl, sizeof(ovl));
ovl.hEvent = readFinishEvent;
DWORD rdCount;

if(ReadFile(rdPipe, buffer, BufferSize, &rdCount, &ovl) == FALSE)
{
  WaitForSingleObject(readFinishEvent, ReadTimeoutMs);
  rdCount = ovl.InternalHigh;
}
CloseHandle(readFinishEvent);
response = QByteArray(buffer, (int)rdCount);
return response;
   WaitForSingleObject(readFinishEvent, ReadTimeoutMs);

哎呀,这是一个非常讨厌的错误,您很幸运能够得到诊断。永远,永远不要忽略 winapi 函数 return 值。当它 returns WAIT_TIMEOUT 时,这会严重失败。处理不当,忘记取消I/O操作

随机灾难在它实际完成时发生,稍后,驱动程序将垃圾喷射到 bufferovl 曾经所在的堆栈中。当您继续调用此函数时,您会得到诊断信息。但通常 any 函数的局部变量可能会损坏。极难诊断,给微软买根雪茄来实现 /RTC

当您获得除 WAIT_OBJECT_0 以外的任何其他 return 值时,您 必须 调用 CancelIo()