TMonitor.GetBoundsRect在VNC触发的Delphi 2007中是否存在访问冲突错误? [英] Does TMonitor.GetBoundsRect have an access violation bug in Delphi 2007 triggered by VNC?

查看:77
本文介绍了TMonitor.GetBoundsRect在VNC触发的Delphi 2007中是否存在访问冲突错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我从运行Delphi 2007中内置的一款大型产品的客户那里获得的崩溃报告,我无法复制,并且甚至没有通过调用堆栈直接涉及任何非VCL代码.

This is a crash report I get from customers running one of our big products built in Delphi 2007, that I am unable to reproduce and which doesn't even have any non-VCL code directly involved via the call stack.

Delphi 2007中TMonitor的VCL源代码非常简单( Forms.pas )

The VCL Source code for TMonitor in Delphi 2007 is very simple (Forms.pas)

TMonitor.GetBoundsRect 在初始化a之后调用win32 API GetMonitorInfo struct的 cbSize ,以便Windows API知道要返回的大小.

TMonitor.GetBoundsRect calls win32 API GetMonitorInfo after initializing a struct's cbSize so that the Windows API knows what size to return.

我已经遍历了这段代码,除非Self指针无效,否则我看不到该级别如何崩溃,尽管我怀疑它实际上可能是 THintWindow 级别发生故障,并且仅在 TMonitor.GetBoundsRect 上,此故障才变为可见的崩溃,因为它以某种方式获得了指向无效的 TMonitor 对象的指针并对其调用了一个方法.

I have been over and over this code and I can't see how this level could crash, unless the Self pointer is invalid, although I suspect it might actually be the THintWindow level malfunctioning, and it is only at the TMonitor.GetBoundsRect that this malfunction becomes a visible crash because somehow it has gotten a pointer to an invalid TMonitor object and invoked a method on it.

function TMonitor.GetBoundsRect: TRect;
var
  MonInfo: TMonitorInfo;
begin
  MonInfo.cbSize := SizeOf(MonInfo);
  GetMonitorInfo(FHandle, @MonInfo);  // <----- CRASH.
  Result := MonInfo.rcMonitor;
end;

通过madExcept进行的崩溃调用堆栈仅可在客户端系统上重现:

Crash call stack via madExcept is only reproduceable on client systems:

main thread ($70):
004f5004 +010 myapp.exe Forms    6361  +2 TMonitor.GetBoundsRect
004f4fe2 +00a myapp.exe Forms    6352  +1 TMonitor.GetWidth
004e022f +06b myapp.exe Controls 9929  +7 THintWindow.ActivateHint
004e0457 +017 myapp.exe Controls 9970  +1 THintWindow.ActivateHintData
004f95fa +31a myapp.exe Forms    8923 +56 TApplication.ActivateHint
004f8fc1 +02d myapp.exe Forms    8728  +8 TApplication.HintTimerExpired
004f61e6 +022 myapp.exe Forms    7083  +3 HintTimerProc
7e4196c2 +00a USER32.dll                    DispatchMessageA
004f7f00 +0fc myapp.exe Forms    8105 +23 TApplication.ProcessMessage
004f7f3a +00a myapp.exe Forms    8124  +1 TApplication.HandleMessage
004f822f +0b3 myapp.exe Forms    8223 +20 TApplication.Run
0155cf77 +2f3 myapp.exe myapp    368  +41 initialization

整个调用堆栈中的所有上述代码都是VCL源代码,都不是我的.

All the code above in the entire call stack is VCL source code, none of it is mine.

除了禁用整个应用程序中的所有提示外,还有什么我可以做些进一步的故障排除或解决的方法吗?

Aside from disabling all Hints in the entire application, is there anything I could do to further troubleshoot this or work around it?

更新:注册和解除注册,以及异常地址:

Update: Registers and disasm, and exception address:

exception class   : EAccessViolation
exception message : Access violation at address 004F5004 in module 'hirepnt.exe'. Read of address 00000004.

cpu registers:
eax = 00000000
ebx = 0012fccc
ecx = 7e42ac2c
edx = 0012fccc
esi = 07b694a8
edi = 0012fd14
eip = 004f5004
esp = 0012fc90
ebp = 0012fd1c

stack dump:
0012fc90  94 fc 12 00 28 00 00 00 - 2c ac 42 7e 70 b3 6f 02  ....(...,.B~p.o.
0012fca0  fc fc 12 00 01 00 00 00 - 70 b3 6f 02 cc 53 4f 00  ........p.o..SO.
0012fcb0  01 00 00 00 01 00 00 00 - 3c 56 4f 00 14 fd 12 00  ........<VO.....
0012fcc0  a8 94 b6 07 00 00 00 00 - e7 4f 4f 00 00 00 00 00  .........OO.....
0012fcd0  4b 64 4f 00 14 fd 12 00 - a8 94 b6 07 00 00 00 00  KdO.............
0012fce0  34 02 4e 00 4c fd 12 00 - c4 5c 40 00 1c fd 12 00  4.N.L....\@.....
0012fcf0  40 fd 12 00 97 fd 12 00 - 0c 23 4d 00 e0 01 00 00  @........#M.....
0012fd00  6d 01 00 00 e0 01 00 00 - 6d 01 00 00 41 02 00 00  m.......m...A...
0012fd10  80 01 00 00 34 fd 12 00 - 10 cc 6e 02 40 fd 12 00  ....4.....n.@...
0012fd20  5d 04 4e 00 d8 fd 12 00 - 0c 23 4d 00 f0 fd 12 00  ].N......#M.....
0012fd30  e0 01 00 00 6d 01 00 00 - 41 02 00 00 7c 01 00 00  ....m...A...|...
0012fd40  f4 fd 12 00 00 96 4f 00 - 00 00 00 00 0c fe 12 00  ......O.........
0012fd50  c4 5c 40 00 f4 fd 12 00 - 8c fe 12 00 c4 61 4f 00  .\@..........aO.
0012fd60  40 41 6f 02 00 00 00 00 - 00 00 00 00 28 05 00 00  @Ao.........(...
0012fd70  15 02 00 00 00 00 00 00 - 00 00 00 00 d9 04 00 00  ................
0012fd80  ac 01 00 00 84 00 00 e0 - 01 00 00 6d 01 00 00 41  ...........m...A
0012fd90  02 00 00 7c 01 00 00 01 - 4f 00 00 00 69 00 00 00  ...|....O...i...
0012fda0  51 00 00 00 6b 00 00 00 - e0 01 00 00 61 01 00 00  Q...k.......a...
0012fdb0  f0 84 22 06 0c 23 4d 00 - e0 01 00 00 6d 01 00 00  .."..#M.....m...
0012fdc0  56 05 00 00 18 00 00 ff - fe ff ff ff fe ff ff ff  V...............

disassembling:
[...]
004f4ff6        push    edi
004f4ff7        add     esp, -$28
004f4ffa        mov     ebx, edx
004f4ffc 6360   mov     dword ptr [esp], $28
004f5003 6361   push    esp
004f5004      > mov     eax, [eax+4]
004f5007        push    eax
004f5008        mov     eax, [$1644560]
004f500d        mov     eax, [eax]
004f500f        call    eax
004f5011 6362   mov     edi, ebx
[...]

推荐答案

最可能是qc #25466 #57953 ),并且修补Forms.pas确实可以解决该问题.就我而言,使用D7只能通过使用远程访问来触发,并且问题/解决方法与D2007相同.

It's most likely qc #53932 (also #25466 #57953), and patching Forms.pas does fix it. In my case, using D7, it only got triggered by using remote access, and the problem/fix is the same as for D2007.

具体来说,补丁是更改TScreen.FindMonitor.这是D7更改,不确定是否需要对D2007进行任何编辑.

Specifically, the patch is to change TScreen.FindMonitor. This is the D7 change, not sure if it needs any edits for D2007.

function TScreen.FindMonitor(Handle: HMONITOR): TMonitor;
var
  I: Integer;
begin
  Result := nil;
  for I := 0 to MonitorCount - 1 do
    if Monitors[I].Handle = Handle then
    begin
      Result := Monitors[I];
//      break;
      Exit;
    end;
  //if we get here, the Monitors array has changed, so we need to clear and reinitialize it
  for i := 0 to MonitorCount-1 do
    TMonitor(Monitors[i]).Free;
  fMonitors.Clear;
  EnumDisplayMonitors(0, nil, @EnumMonitorsProc, LongInt(FMonitors));
  for I := 0 to MonitorCount - 1 do
    if Monitors[I].Handle = Handle then
    begin
      Result := Monitors[I];
      Exit;
    end;
end;

这篇关于TMonitor.GetBoundsRect在VNC触发的Delphi 2007中是否存在访问冲突错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆