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)
WaitForSingleObject(readFinishEvent, ReadTimeoutMs);
Run Code Online (Sandbox Code Playgroud)
哎呀,这是一个非常讨厌的错误,你很幸运能得到诊断.永远不要忽略winapi函数的返回值.当它返回WAIT_TIMEOUT时,这会严重失败.你没有正确处理,你忘了取消I/O操作.
随后的灾难在它实际完成时发生,之后,驱动程序将垃圾喷射到堆栈中,buffer并且ovl曾经在其中找到过.当您继续调用此功能时,您将获得诊断.但一般来说,函数的任何局部变量都可能被破坏.非常难以诊断,购买微软雪茄来实施/ RTC
你必须调用CancelIo()当你得到比WAIT_OBJECT_0其他任何返回值.
| 归档时间: |
|
| 查看次数: |
120 次 |
| 最近记录: |