Delphi XE5 / 32,在Windows10 / 64上,生成Win32 VCL可执行文件。
我收到与表单创建相关的间歇性访问冲突错误。一些最终用户也很少看到这个错误(我目前正在进行小规模试验,测试组大约有20个用户)。
这种情况持续了好几个月,直到最近,我发现这个问题的尝试因为很难重现而受挫。但是,我现在终于能够建立一个可靠地再现错误的环境。 Bizzarely,我发现它是由我的GMail帐户中的某些电子邮件在Chrome浏览器中显示的。导致问题的电子邮件完全一致 - 请参阅https://www.devexpress.com/Support/Center/Question/Details/T395896中的视频。 (我最初将此查询发布到DevExpress支持论坛,因为我怀疑其中一个组件是原因,但现在我对此表示怀疑)。
我现在暂时禁用了我的启动画面,并更改了以前的自动创建数据模块,以便在主窗体的OnCreate中创建。 DPR现在非常简单:
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.Title := 'Topshare V3';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
也就是说,在CreateForm之前没有任何事情发生在程序的主要表单中。
当错误发生时,程序要么在Application.CreateForm(TMainForm,MainForm)中静默挂起,要么在调用主窗体的OnCreate之前;或者它在OnCreate之前终止,并调用表单的OnDestroy。因此,在解析DFM期间会出现问题。
如果我在错误处于活动状态时在IDE中以调试模式执行程序,则在Application.CreateForm(TMainForm,MainForm)期间会引发多个AV。这些只能从IDE中看出,大概是在try..except块中。如果我在第一个上单击Break,则调用堆栈通常类似于:
System.SysGetMem(???)
:00405423 SysGetMem + $43
System.Classes.TReader.ReadComponent(nil)
System.Classes.TReader.ReadDataInner(???)
System.Classes.TReader.ReadData($7BCCD90)
System.Classes.TComponent.ReadState(???)
Vcl.Controls.TControl.ReadState($9C6F098)
Vcl.Controls.TWinControl.ReadState($9C6F098)
:00aa0bcd TcxCustomGrid.ReadState + $29
System.Classes.TReader.ReadDataInner(???)
System.Classes.TReader.ReadData($7BF4230)
System.Classes.TComponent.ReadState(???)
Vcl.Controls.TControl.ReadState($9C6F098)
Vcl.Controls.TWinControl.ReadState($9C6F098)
System.Classes.TReader.ReadComponent(nil)
System.Classes.TReader.ReadDataInner(???)
System.Classes.TReader.ReadData($7BF3F50)
System.Classes.TComponent.ReadState(???)
Vcl.Controls.TControl.ReadState($9C6F098)
Vcl.Controls.TWinControl.ReadState($9C6F098)
System.Classes.TReader.ReadComponent(nil)
System.Classes.TReader.ReadDataInner(???)
System.Classes.TReader.ReadData($9B9C7A0)
System.Classes.TComponent.ReadState(???)
Vcl.Controls.TControl.ReadState($9C6F098)
Vcl.Controls.TWinControl.ReadState($9C6F098)
Vcl.Forms.TCustomForm.ReadState($9C6F098)
System.Classes.TReader.ReadRootComponent($9B9C7A0)
System.Classes.TStream.ReadComponent($9B9C7A0)
System.Classes.InternalReadComponentRes(???,???,$9B9C7A0)
System.Classes.InitComponent(TMainForm)
System.Classes.InitInheritedComponent($9B9C7A0,TForm)
Vcl.Forms.TCustomForm.Create(???)
Vcl.Forms.TApplication.CreateForm(???,(no value))
TopshareV3.TopshareV3
SysGetMem的明显参与使我想到了这个问题:Delphi XE5 Acces Violation on app start
因此我启用了范围检查和溢出检查,但这没有帮助。
DFM一定有问题。
一个方面是主表单继承自祖先表单类型。祖先形式没有组件,只有一些方法。祖先形式的源代码不包含默认的全局变量声明。因此,主要表格的表格声明是: TMainForm = class(TABase)
并且DFM包含: 继承了MainForm:TMainForm
表单包含几个嵌套框架,还使用多个ActionManagers,ActionToolbars,ActionMainMenubar,PopupActionbar和dxSkinController。
任何人都可以进一步了解要寻找什么,或者如何继续前进?
编辑:上面显示的调用堆栈是在第一个AV之后。但我已经完成了你建议的追踪。我在System.Classes中的第10169行在TReader.ReadComponent中放置了一个断点。然后我在" Parent.name"上添加手表。和" CompName"。然后,在IDE中再次启动,我看到正在创建的各种主要表单组件。
以前,当首先创建数据模块时,我会看到创建了许多组件,但是在使用显示第一个cxGrid(DevExpress)视图的手表命中断点后,AV总是会发生。如果我在表单中添加了一个额外的网格(并且在要创建的第一个面板上),而没有设置任何属性,则新网格似乎会触发AV。换句话说,似乎cxGrid是问题所在 - 因此我与DevExpress支持联系。
但推迟创建数据模块,并消除我的启动画面,已经改变了一些事情(尽管AV仍在发生)。现在,它的进展远远超出了第一个网格;虽然cxGrid似乎仍然存在,但我现在还不确定它是否相关(我在主窗体上有很多网格)。
编辑:在IDE中运行,有3个AV(如果我在每个后点击继续) - 然后程序在我的OnCreate代码执行之前挂起:第一个是$ C0000005,消息'访问冲突在0x0040541d:读取地址0x002d001c&#39 ;;和,两次,$ C0000005,消息'访问冲突在0x00a8107a:读取地址0x00000068'。编辑:我在类#10169的初始断点现在执行了几十次,因为DFM的表单组件被处理。在现在关键的组件(仍然是cxGrid视图)上,执行步骤从类#10169(在Treader.ReadComponent中)到CreateComponent#10114,到Result.create#10129。从这里开始有一个循环(或递归),它包括一个从System#16752开始的汇编程序块,以及#15511处的空Tobject.Create。系统#15511的断点执行29次。然后,第30次通过,AV发生在系统#16757,CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance
编辑:当没有错误条件时执行执行时,事情看起来与存在时基本相同:即,相同的调用序列。似乎遵循上述段落中描述的相同顺序 - 除了第30遍或之后没有AV。
答案 0 :(得分:1)
我已将问题缩小到DevExpress的dxSpreadSheetCore单元。如果我在任何Uses子句中包含它,则会显示错误;如果我省略它,没有错误。我已将问题提交给DevExpress,虽然我无法简化我的应用程序,也无法为它们提供有用的错误演示。
根据这里的评论,我的假设是dxSpreadSheetCore(或其依赖单元)的初始化部分中的某些内容导致堆损坏。