问题
We have a large application that works fine in Delphi 2006. We've moved it to XE5 and are experiencing frequent sporadic Access Violations. We're using VCL forms and a number of DevExpress and other third party components. We're working in Windows 7 Professional with Delphi XE Enterprise, Version 19.0.14356.6604.
We've looked on line, here and elsewhere, for postings about A/Vs after porting to XE5 but haven't found anything that seems relevant to our problem.
Here's what we know about the A/Vs:
- They usually occur at the same address: 0x50059f27. Sometimes they happen at 0x5005eb86, usually after an A/V has already been triggered at the other address.
- They happen from various different locations and actions in the app.
- They aren't 100% reproducible. Sometimes a rebuild of the project will eliminate one trigger but then something else will trigger it. They seem to stay fairly consistently reproducible within builds.
- They are generally connected with either opening a dialog or activating a query that returns a substantial number of records (1,000+).
- They don't happen with the D2006 version (which we run on XP boxes or in an XP Virtual Machine). - They don't happen when we run the XE5 application in XP-SP3 compatibility mode.
- If we break after a typical A/V, the pointer will be in System.pas at Line 562, in the
{$IFDEF CPUX86}
asm section ofprocedure Move(const Source; var Dest; Count: NativeInt);
The section of code is appended below. The line isFILD QWORD PTR [EAX] {Last 8}
.
We're guessing that the issue has to do with how our app deals with Windows 7 memory management but we don't know how to figure out where it's going wrong. A sample call stack is appended.
Can anyone suggest how we might proceed to troubleshoot this problem? Are there third-party debugging tools that would help? Are there Delphi IDE tools we can be using to try to track this down? Articles that might be useful?
Many thanks for any suggestions.
Here's the section of System.pas code where the A/Vs occur:
@@LargeForwardMove: {4-Byte Aligned}
PUSH EDX
FILD QWORD PTR [EAX] {First 8}
LEA EAX, [EAX+ECX-8]
LEA ECX, [ECX+EDX-8]
FILD QWORD PTR [EAX] {Last 8} // <- Debug break pointer will be here.
PUSH ECX
NEG ECX
AND EDX, -8 {8-Byte Align Writes}
LEA ECX, [ECX+EDX+8]
POP EDX
And here's a sample from the Call Stack:
vcl.Vcl.Buttons.TBitBtn.Click
vcl.Vcl.StdCtrls.TCustomButton.CNCommand(???)
vcl.Vcl.Controls.TControl.WndProc((48401, 3186, 724082, 0, 3186, 0, (), 3186, 11, (), 0, 0, ()))
vcl.Vcl.Controls.TWinControl.WndProc((48401, 3186, 724082, 0, 3186, 0, (), 3186, 11, (), 0, 0, ()))
vcl.Vcl.StdCtrls.TButtonControl.WndProc((48401, 3186, 724082, 0, 3186, 0, (), 3186, 11, (), 0, 0, ()))
vcl.Vcl.Controls.TControl.Perform(???,???,724082)
vcl.Vcl.Controls.DoControlMsg(???,(no value))
vcl.Vcl.Controls.TWinControl.WMCommand((273, (), 3186, 0, (), 724082, 0))
vcl.Vcl.Controls.TControl.WndProc((273, 3186, 724082, 0, 3186, 0, (), 3186, 11, (), 0, 0, ()))
vcl.Vcl.Controls.TWinControl.WndProc((273, 3186, 724082, 0, 3186, 0, (), 3186, 11, (), 0, 0, ()))
vcl.Vcl.Controls.TWinControl.MainWndProc(???)
rtl.System.Classes.StdWndProc(987008,273,3186,724082)
:772462fa ; C:\Windows\syswow64\USER32.dll
:77246d3a USER32.GetThreadDesktop + 0xd7
:77246de8 ; C:\Windows\syswow64\USER32.dll
:77246e44 ; C:\Windows\syswow64\USER32.dll
:77ad010a ntdll.KiUserCallbackDispatcher + 0x2e
:772496c5 USER32.SendMessageW + 0x4c
:75184601 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\comctl32.dll
:75184663 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\comctl32.dll
:751844ed ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\comctl32.dll
:772462fa ; C:\Windows\syswow64\USER32.dll
:77246d3a USER32.GetThreadDesktop + 0xd7
:77250d27 USER32.GetClientRect + 0xc5
:77250d4d USER32.CallWindowProcW + 0x1b
vcl.Vcl.Controls.TWinControl.DefaultHandler(???)
:5046777f TWinControl.DefaultHandler + $EB
:5046766e TWinControl.WndProc + $5CA
:50487a69 TButtonControl.WndProc + $71
:501749c6 StdWndProc + $E
:772462fa ; C:\Windows\syswow64\USER32.dll
:77246d3a USER32.GetThreadDesktop + 0xd7
:772477c4 ; C:\Windows\syswow64\USER32.dll
:7724788a USER32.DispatchMessageW + 0xf
回答1:
That looks like a simple bug in your program. Possibly accessing memory after release. Or a buffer overrun. What you need to do is some debugging. The tools you need are:
- Range checking compiler option enabled. This finds most buffer overruns.
- FastMM full version with full debug settings. This should pin-point errors like access after free.
- madExcept. This will provide stack traces at the point of the exception. That's crucial because it lets you see how you got to this point in the code. That in turn helps you see what data is being passed and should give you clues as to what you've done wrong. I know you have a stack trace but it doesn't look right. After all,
TBitBtn.Click
does not callMove
directly.
Don't kid yourself that the fact that you don't see the fault on XP somehow means that the blame lies with the OS. Or that somehow you need to handle memory differently in different versions of the OS. Plenty of application programming errors are benign on some systems but manifest on others. Odds are high that your program is broken everywhere but you by chance get away with it some of the time.
来源:https://stackoverflow.com/questions/22885790/sporadic-access-violation-after-porting-from-d2006-to-xe5-doesnt-happen-in-xp