Delphi Peek消息访问冲突Delphi 2009 Windows API

Delphi Peek消息访问冲突Delphi 2009 Windows API,delphi,winapi,access-violation,peekmessage,Delphi,Winapi,Access Violation,Peekmessage,定期从消息中获取访问冲突。这不是我对PeekMessage的调用,它来自Application.Run。MadExcept的堆栈跟踪显示应用程序。运行调用PeekMessage的命令,该命令反过来调用kiUserCallBackDispatcher 德尔福2009 堆栈跟踪是: callstack crc : $0202d0d7, $a09d5671, $3195cde5 exception number : 1 exception class : EAccessViolation

定期从消息中获取访问冲突。这不是我对PeekMessage的调用,它来自Application.Run。MadExcept的堆栈跟踪显示应用程序。运行调用PeekMessage的命令,该命令反过来调用kiUserCallBackDispatcher

德尔福2009

堆栈跟踪是:

callstack crc     : $0202d0d7, $a09d5671, $3195cde5
exception number  : 1
exception class   : EAccessViolation
exception message : Access violation at address 0202D0D7. Write of address 00310038.

main thread ($1650):
0202d0d7 +000 ???
7c90e470 +010 ntdll.dll                               KiUserCallbackDispatcher
7e4193fd +162 USER32.dll                              PeekMessageW
0050b2a4 +01c infraWrapper90.exe Forms                TApplication.ProcessMessage
0050b3ea +00a infraWrapper90.exe Forms                TApplication.HandleMessage
0050b715 +0c9 infraWrapper90.exe Forms                TApplication.Run
我假设这意味着PeekMessage()正在调用我的一个窗口 过程来处理消息,但它找不到该窗口过程。起初,我不明白为什么Peekmessage会调用任何窗口过程,因为它只是在偷看消息,但通过进一步阅读这里和其他地方,我认为我看到了:

  • PeekMessage()将处理从其他线程发送的SendMessages()
  • PeekMessage()有时会处理绘制消息
  • 其他人报告说看到PeekMessage调用其他消息的窗口过程,例如WM_ERASEBKGND
从MSDN:

在此调用过程中,系统会传递挂起的非排队消息,即使用
SendMessage
SendMessageCallback
SendMessageTimeout
SendNotifyMessage
函数发送给调用线程所拥有的windows的消息


我不太明白这一点,因为我认为SendMessage()调用可以立即处理。其他人似乎认为只有当SendMessage来自另一个线程时才适用

我不能在独立的项目中重复这一点。从错误中可以看出,PeekMessage调用的是一个不再存在的窗口过程,但我自己也尝试过这样做,故意破坏一个表单,然后对一个无效的窗口句柄执行SendMessage()和Postmessage(),Windows似乎忽略了它。我尝试过将消息从表单的析构函数发送到表单本身以及其他各种事情,但我无法让它失败

还有什么要检查的建议吗?提前谢谢


Rick

“我不太理解这一点,因为我认为SendMessage()调用是立即处理的。其他人似乎认为只有当SendMessage来自另一个线程时,才会应用这一点。”嗯,
SendMessage
调用必须在拥有该窗口的线程的上下文中执行。您不能在任意点将代码注入正在运行的线程。因此,机制是使用对PeekMessage、GetMessage等例程的调用来分派非排队消息。不过,我认为您的基本分析是正确的。到目前为止,最可能的情况是消息被发送到不再存在的窗口。我假设函数的
LPMSG
参数指向无效地址。通过捕获异常并检查指针,可以轻松地检查这一点。如果句柄错误(关闭),则应该是错误代码,而不是访问冲突。“写入地址00310038”?可能您有一个包含“81”的字符串,并将其视为一个地址。Windows进程是否可能驻留在已卸载的DLL中?