2013-03-06 84 views
2

這是我從客戶運行的一個崩潰報告,運行我們在Delphi 2007中構建的一個大型產品,我無法重現,甚至沒有任何非VCL代碼直接通過調用堆棧涉及。TMonitor.GetBoundsRect在VNC觸發的Delphi 2007中是否存在訪問衝突錯誤?

在2007年德爾福TMonitor VCL的源代碼初始化後非常簡單(Forms.pas

TMonitor.GetBoundsRect調用Win32 API的GetMonitorInfo一個 結構的cbSize以便在Windows API知道返回什麼尺寸。

我一直在這段代碼,我看不到這個級別會如何崩潰,除非自我指針無效,但我懷疑它可能實際上是THintWindow級別的故障,並且它只在TMonitor.GetBoundsRect這個故障變成了一個可見的崩潰,因爲它不知何故已經得到了一個指向一個無效的TMonitor對象並在其上調用了一個方法。經由madExcept

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

崩潰調用棧僅reproduceable在客戶端系統:

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源代碼,它沒有一個是我的。

除了禁用整個應用程序中的所有提示,有什麼我可以做的,以進一步排除故障或解決它嗎?

更新:寄存器和反彙編,以及異常地址:

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 [email protected] 
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 
[...] 
+0

我會親自初始化'TMonitorInfo'結構,例如通過'ZeroMemory'。 – TLama 2013-03-06 16:20:53

+0

我不知道是不是這樣:http://qc.embarcadero.com/wc/qcmain.aspx?d=53932 – 2013-03-06 16:21:37

+1

@TLama這只是偏執狂。不會幫助。 – 2013-03-06 16:30:47

回答

3

這是最有可能的QC #53932(也#25466#57953),和修補Forms.pas並解決它。在我的情況下,使用D7,它只能通過遠程訪問觸發,問題/修復與D2007相同。

具體來說,該補丁是要更改TScreen.FindMonitor。這是D7的變化,不確定它是否需要對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; 
+0

我的客戶回到我身邊,他們使用RealVNC(不是ultraVNC,但足夠接近)發生這種情況。 – 2013-03-07 17:37:51