从 D2006 移植到 XE5 后偶尔出现访问冲突,在 XP 兼容模式下不会发生 [英] Sporadic Access Violation after porting from D2006 to XE5, doesn't happen in XP compatibility mode

查看:19
本文介绍了从 D2006 移植到 XE5 后偶尔出现访问冲突,在 XP 兼容模式下不会发生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个在 Delphi 2006 中运行良好的大型应用程序.我们已将其移至 XE5,并且经常遇到偶发性访问冲突.我们正在使用 VCL 表单和许多 DevExpress 和其他第三方组件.我们正在 Windows 7 Professional 和 Delphi XE Enterprise,版本 19.0.14356.6604.

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.

在移植到 XE5 之后,我们在网上、这里和其他地方查看了有关 A/V 的帖子,但没有发现任何与我们的问题相关的内容.

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.

以下是我们对 A/V 的了解:

Here's what we know about the A/Vs:

  • 它们通常出现在相同的地址:0x50059f27.有时它们发生在 0x5005eb86,通常是在另一个地址触发了 A/V 之后.
  • 它们发生在应用中的各种不同位置和操作中.
  • 它们不是 100% 可重现的.有时,项目的重建会消除一个触发因素,但随后会触发其他因素.它们似乎在构建中保持相当一致的可重现性.
  • 它们通常与打开对话框或激活返回大量记录(1,000+)的查询有关.
  • D2006 版本(我们在 XP 机器或 XP 虚拟机上运行)不会发生这种情况.- 当我们在 XP-SP3 兼容模式下运行 XE5 应用程序时,它们不会发生.
  • 如果我们在典型的 A/V 之后中断,指针将在 System.pas 的第 562 行,在 {$IFDEF CPUX86} asm 部分的 procedure Move(const Source; var Dest; Count: NativeInt); 下面附上一段代码.该行是 FILD QWORD PTR [EAX] {Last 8}.
  • 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 of procedure Move(const Source; var Dest; Count: NativeInt); The section of code is appended below. The line is FILD QWORD PTR [EAX] {Last 8}.

我们猜测问题与我们的应用程序如何处理 Windows 7 内存管理有关,但我们不知道如何找出哪里出错了.附加了一个示例调用堆栈.

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.

谁能建议我们如何继续解决此问题?是否有第三方调试工具可以提供帮助?我们是否可以使用 Delphi IDE 工具来尝试跟踪此问题?可能有用的文章?

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.

这是发生 A/V 的 System.pas 代码部分:

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:Windowssyswow64USER32.dll
:77246d3a USER32.GetThreadDesktop + 0xd7
:77246de8 ; C:Windowssyswow64USER32.dll
:77246e44 ; C:Windowssyswow64USER32.dll
:77ad010a ntdll.KiUserCallbackDispatcher + 0x2e
:772496c5 USER32.SendMessageW + 0x4c
:75184601 ; C:WindowsWinSxSx86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2comctl32.dll
:75184663 ; C:WindowsWinSxSx86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2comctl32.dll
:751844ed ; C:WindowsWinSxSx86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2comctl32.dll
:772462fa ; C:Windowssyswow64USER32.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:Windowssyswow64USER32.dll
:77246d3a USER32.GetThreadDesktop + 0xd7
:772477c4 ; C:Windowssyswow64USER32.dll
:7724788a USER32.DispatchMessageW + 0xf

推荐答案

这看起来像是程序中的一个简单错误.可能在释放后访问内存.或者缓冲区溢出.你需要做的是一些调试.您需要的工具是:

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:

  1. 范围检查编译器选项已启用.这会发现大多数缓冲区溢出.
  2. FastMM 完整版,带有完整的调试设置.这应该查明诸如免费访问之类的错误.
  3. mad除了.这将在异常点提供堆栈跟踪.这很重要,因为它可以让您看到如何在代码中达到这一点.这反过来可以帮助您查看正在传递的数据,并且应该为您提供有关您做错了什么的线索.我知道你有一个堆栈跟踪,但它看起来不对.毕竟TBitBtn.Click并没有直接调用Move.
  1. Range checking compiler option enabled. This finds most buffer overruns.
  2. FastMM full version with full debug settings. This should pin-point errors like access after free.
  3. 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 call Move directly.

不要自欺欺人,因为您看不到 XP 上的错误,这意味着责任在于操作系统.或者您需要在不同版本的操作系统中以不同方式处理内存.许多应用程序编程错误在某些系统上是良性的,但在其他系统上却很明显.你的程序到处都被破坏的可能性很高,但你有时会侥幸逃脱.

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.

这篇关于从 D2006 移植到 XE5 后偶尔出现访问冲突,在 XP 兼容模式下不会发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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