即使缓冲区被覆盖以进行挂起操作,WriteFile也会成功

时间:2014-04-16 07:34:04

标签: c++ c winapi named-pipes

在我的程序中(发布到此question),我在客户端进行了以下更改:

wretry:   
   cbToWrite = _stprintf(chBuf[0], TEXT("Message %d from Client"), retrycount - numberofsend + 1);
   cbToWrite *= sizeof(TCHAR);

   fSuccess = WriteFile(hPipe, chBuf[0], cbToWrite,
  &cbWritten, &woverlapped[retrycount-numberofsend]);

这样,现在每次都会使用相同的缓冲区进行写入。

在这种情况下,WriteFile每次都会等待,因为它返回ERROR_IO_PENDING。由于每次都会覆盖缓冲区的内容,因此服务器应该接收写入缓冲区的最后一条消息。但服务器正在接收消息而没有任何问题。

是否意味着首先将消息复制到某个内部缓冲区?我可以销毁缓冲区并期望邮件将被传递到服务器吗?

2 个答案:

答案 0 :(得分:4)

再次引用MSDN:

  

lpBuffer [in]   指向包含要写入文件或设备的数据的缓冲区的指针。   此缓冲区必须在写入操作期间保持有效。在写操作完成之前,调用者不得使用此缓冲区。

因此,如果在执行写入操作时弄乱缓冲区,则无法保证您的消息安全到达。你绝对不应该破坏缓冲区

答案 1 :(得分:1)

您的代码实际上是使用未定义的行为。来自WriteFile文档:

  

在写操作使用缓冲区时访问输出缓冲区可能会导致从该缓冲区写入的数据损坏。在写操作完成之前,应用程序不得写入,重新分配或释放写操作正在使用的输出缓冲区。

Raymond Chen指出,appearing to succeed is undefined behaviour

  

未定义的行为意味着任何事情都可能发生。该程序可能会立即崩溃。五分钟后可能会崩溃。它可能会发送电子邮件给你的老板说你搞砸了然后读你的Vogon诗歌。或者可能不是。

您的代码现在可能正常运行,但它可能会在将来某个时候停止运行。这可能是因为您内置了版本,或者Microsoft更改了WriteFile的基础工作或随机机会。