WriteFile成功,即使缓冲区被挂起的操作覆盖

WriteFile succeeded even when buffer is overwritten for pending operation

本文关键字:挂起 操作 覆盖 缓冲区 成功 WriteFile      更新时间:2023-10-16

在我的程序(发布到这个问题中)中,我在客户端进行了以下更改:

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。由于缓冲区的内容每次都会被覆盖,服务器应该会收到写入缓冲区的最后一条消息。但服务器接收消息没有任何问题。

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

再次引用MSDN:

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

因此,如果在进行写操作时损坏了缓冲区,那么您的消息似乎无法保证安全到达。您绝对不应该破坏缓冲区

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

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

正如Raymond Chen所指出的,看似成功是未定义的行为

未定义的行为意味着任何事情都可能发生。程序可能会立即崩溃。它可能在五分钟后坠毁。它可能会给你的老板发电子邮件,说你搞砸了,然后给你读《Vogon》的诗。也许不是。

您的代码现在可能可以工作,但可能在将来某个时候停止工作。这可能是因为你已经内置了版本,或者微软改变了WriteFile的底层工作方式,或者是随机机会。