【问题标题】:Asynchronous ReadFile() causing run-time errors?异步 ReadFile() 导致运行时错误?
【发布时间】:2015-11-02 11:09:29
【问题描述】:

我正在实现一个读取子进程输出的函数。我的程序一般是单线程的,我只使用异步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 ┘

否则它只写入这些 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;

【问题讨论】:

  • 您的OVERLAPPED 结构是否恰好超出范围,而ReadFile 调用正在进行中?您发布的代码暗示,它没有。这是您使用的确切代码吗?

标签: c++ winapi asynchronous visual-studio-2008


【解决方案1】:
   WaitForSingleObject(readFinishEvent, ReadTimeoutMs);

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

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

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

【讨论】:

    猜你喜欢
    • 2010-09-14
    • 2015-12-09
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    相关资源
    最近更新 更多