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

Mel*_*ius 0 c++ winapi asynchronous visual-studio-2008

我正在实现一个读取子进程输出的函数.我的程序通常是单线程的,我只使用异步API来实现读取超时(不适用于同步版本ReadFile()).我创建一个OVERLAPPED结构,调用异步ReadFile(),然后WaitForSingleObject()使用所需的超时.

当读取功能完成时,MSVC有时会报告:

运行时检查失败#2 - 变量'rdCount'周围的堆栈已损坏.

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

… cc cc cc cc 00 00 00 00 00 00 00 00 0f 00 00 00 cc cc cc cc …
                                      ? rdCount ?
Run Code Online (Sandbox Code Playgroud)

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

… cc cc cc cc 02 01 00 00 cc cc cc cc 00 00 00 00 cc cc cc cc …
                                      ? rdCount ?
Run Code Online (Sandbox Code Playgroud)

有趣的是,当我添加一些padding大小至少48字节的填充(参见数组)时,问题就会消失,因为写入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;
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 7

   WaitForSingleObject(readFinishEvent, ReadTimeoutMs);
Run Code Online (Sandbox Code Playgroud)

哎呀,这是一个非常讨厌的错误,你很幸运能得到诊断.永远不要忽略winapi函数的返回值.当它返回WAIT_TIMEOUT时,这会严重失败.你没有正确处理,你忘了取消I/O操作.

随后的灾难在它实际完成时发生,之后,驱动程序将垃圾喷射到堆栈中,buffer并且ovl曾经在其中找到过.当您继续调用此功能时,您将获得诊断.但一般来说,函数的任何局部变量都可能被破坏.非常难以诊断,购买微软雪茄来实施/ RTC

必须调用CancelIo()当你得到比WAIT_OBJECT_0其他任何返回值.