首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重叠串口和蓝屏死亡

重叠串口和蓝屏死亡
EN

Stack Overflow用户
提问于 2009-07-12 19:47:06
回答 2查看 2.2K关注 0票数 2

我创建了一个异步处理串行端口的类。我用它来和调制解调器通讯。我不知道为什么,但有时,当我关闭我的申请,我得到蓝色屏幕和我的电脑重新启动。我一步一步地记录我的代码,但是当BSOD出现时,当我的计算机重新启动时,我记录数据的文件只包含空格。所以我不知道,BSOD的原因是什么。

我仔细地查看了我的代码,发现了问题的几个可能原因(我正在寻找所有可能导致访问未分配内存并导致AV异常的原因)。

当我重新思考异步操作的想法时,我想到了一些事情。请核实这些意见是否正确:

1) WaitCommEvent()接受指向重叠结构的指针。因此,如果在函数中调用WaitCommEvent(),然后离开函数,则重叠结构不能是局部变量,对吗?事件掩码变量和事件句柄也是,对吗?

2) ReadFile()和WriteFile()也接受对变量的引用或指针。因此,所有这些变量都必须是可访问的,直到重叠的读或写操作完成,对吗?

3)我只调用WaitCommEvent()一次,并在循环中检查其结果,同时执行其他操作。因为我不知道如何终止异步操作(可能吗?),当我破坏保留句柄到串行端口的类时,我首先关闭句柄,然后在调用WaitCommEvent()函数时使用的重叠结构中等待事件。我这样做是为了确保异步等待comm事件的线程不会访问我类中被销毁的任何字段。这是个好主意还是愚蠢?

代码语言:javascript
复制
try
  CloseHandle(FSerialPortHandle);
  if Assigned(FWaitCommEvent) then
    FWaitCommEvent.WaitFor(INFINITE);      
finally
  FSerialPortHandle := INVALID_HANDLE_VALUE;
  FreeAndNil(FWaitCommEvent);
end;

在我注意到所有这些之前,在第一点和第二点中提到的大多数变量都是称为上述三种方法的函数的局部变量。这是BSOD的原因,还是我应该在代码中寻找其他一些错误?

当我更正代码时,BSOD停止出现,但这可能是个巧合。你怎么想的?

任何想法都将不胜感激。提前谢谢。

我阅读了CancelIo()函数文档,它声明该方法取消了调用线程发出的所有I/O操作。如果我知道FWaitCommEvent ()是由与调用CancelIo()线程不同的线程发出的,那么在调用CancelIo()之后等待CancelIo()可以吗?

代码语言:javascript
复制
  if Assigned(FWaitCommEvent) and CancelIo(FSerialPortHandle) then
  begin
    FWaitCommEvent.WaitFor(INFINITE);
    FreeAndNil(FWaitCommEvent);
  end;

我检查了在这种情况下发生了什么,调用这段代码的线程没有陷入僵局,即使它没有发出WaitCommEvent()。我在Windows 7上进行了测试(如果重要的话)。我可以把密码留在原样或危险吗?也许我误解了文档,这就是我提出问题的原因。我很抱歉问了这么多问题,但我真的需要确定这一点。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-07-12 21:12:11

  1. 是的,您确实需要在重叠操作期间保持TOverlapped结构可用。您将在某个时候调用GetOverlappedResultGetOverlappedResult说它应该接收一个指向在启动重叠操作时使用的结构的指针。如果需要,事件掩码和句柄可以存储在局部变量中;无论如何,您将在TOverlapped结构中保存它们的副本。
  2. 是的,ReadFileWriteFile使用的缓冲区必须保持有效。他们不制作自己的本地副本在内部使用。ReadFile的文档甚至这样说: 此缓冲区在读取操作期间必须保持有效。在读取操作完成之前,调用方不能使用此缓冲区。

如果您没有遵守该规则,那么您很可能会进入无保留的堆栈空间,这很容易导致各种意想不到的行为。

  1. 若要取消重叠的I/O操作,请使用CancelIo。在确定相关操作已经终止之前,必须不释放TOverlapped记录的内存。同样,对于您正在读或写的缓冲区。CancelIo不会立即取消该操作,因此您的缓冲区可能仍然在使用中,即使在您调用它之后。
票数 4
EN

Stack Overflow用户

发布于 2009-07-12 21:34:38

作为标准用户运行的应用程序永远不能导致错误检查(a.k.a )。( BSOD)(以管理员身份运行的应用程序必须竭尽全力才能做到这一点。)要么你遇到了一个驱动程序错误,要么你的硬件坏了。

默认情况下,当发生错误检查时,Windows被配置为在%SystemRoot%\minidump中保存一个微型程序。您可以通过在WinDbg中加载minidump文件、配置WinDbg以使用Microsoft公共符号存储以及在WinDbg中运行!analyze -v命令来确定有关崩溃的更多信息。至少,这应该可以确定哪些驱动程序可能是错误的(虽然我猜这是您的调制解调器驱动程序)。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1116751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档