1
votes

Delphi XE5/32, on Windows10/64, generating Win32 VCL executable.

I am getting intermittent Access Violation errors that are associated with form creation. This error has also been seen, rarely, by some end-users (I'm currently in small-scale trials, with a test group of about 20 users).

This has been going on for months and until recently my attempts to find the problem were frustrated by the fact that it was so hard to reproduce. However, I have now finally been able to establish an environment that reproduces the error quite reliably. Bizzarely, I have discovered it is triggered by certain emails being displayed in my GMail account, in Chrome browser. The emails that cause the problem are completely consistent - see the video in https://www.devexpress.com/Support/Center/Question/Details/T395896. (I initially posted this query to the DevExpress support forum because I suspected one of their components was the cause, however now I doubt this).

I have now disabled my splash screen temporarily, and changed my previous auto-create datamodules to be created in the main form's OnCreate. The DPR is now, very simply:

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.Title := 'Topshare V3';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.

That is, nothing happens prior to the CreateForm for the program's main form.

When the error is happening, the program either hangs silently during Application.CreateForm(TMainForm, MainForm), and before the main form's OnCreate is invoked; or it terminates before OnCreate, and invokes the form's OnDestroy. So the problem is occurring during the parsing of the DFM.

If I step the program in debug mode within the IDE when the error is active, there are several AVs raised during Application.CreateForm(TMainForm, MainForm). These are only apparent from the IDE so are, presumably, within try..except blocks. If I click Break on the first of these, the Call Stack is usually something like:

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

The apparent involvement of SysGetMem lead me to this Question: Delphi XE5 Acces Violation on app start

Accordingly I have enabled both Range Checking and Overflow Checking, but this does not help.

There must be something wrong with the DFM.

One aspect is that the main form inherits from an ancestor form type. The ancestor form has no components, just some methods. The ancestor form's source code does not include the default global variable declaration. So, the main form's form declaration is: TMainForm = class(TABase)

and the DFM contains: inherited MainForm: TMainForm

The form contains several nested frames, and also uses several ActionManagers, ActionToolbars, an ActionMainMenubar, a PopupActionbar, and a dxSkinController.

Can anyone shed any further light on what to look for, or how to proceed further??

EDIT: The call stack shown above is After the first AV. But I have already done the tracing you suggest. I put a breakpoint in System.Classes at line #10169, in TReader.ReadComponent. I then add watches on "Parent.name" and "CompName". Then, starting again in the IDE, I see the various main form components being created.

Previously, when the datamodules were being created first, I would see a number of components created, but the AV would always happen after hitting the breakpoint with watches showing the first View of the first cxGrid (DevExpress). If I added an extra grid to the form (and on the first panel to be created), without any properties being set, then the new grid would appear to trigger the AV. In other words, it seemed like the cxGrid was the problem - hence my contact with DevExpress support.

But postponing the creation of the datamodules, and eliminating my splash screen, has changed things (although the AV is still occurring). Now, it progresses well beyond the first grid; and, although a cxGrid still seems to be involved, I'm not sure that's relevant now (I have a lot of grids on the main form).

EDIT: Running in the IDE, there are 3 AVs (if I click Continue after each) - then the program hangs before my code in OnCreate executes: the first is $C0000005 with message 'access violation at 0x0040541d: read of address 0x002d001c'; and, twice, $C0000005 with message 'access violation at 0x00a8107a: read of address 0x00000068'.

EDIT: My initial breakpoint at Classes # 10169 now executes a few dozen times as the form components from the DFM are processed. On the now-critical component (still a cxGrid view), execution steps from Classes #10169 (in Treader.ReadComponent), to CreateComponent #10114, to Result.create #10129. From here there is a loop (or recursion) that includes an assembler block beginning at System #16752, and empty Tobject.Create at #15511. A breakpoint at System #15511 executes 29 times. Then, the 30th time through, the AV occurs at System #16757, CALL DWORD PTR [EAX] + VMTOFFSET TObject.NewInstance

EDIT: When stepping through execution when there's no error condition, things seem essentially the same as when there is: that is, the same sequence of calls. The same sequence described in the para above seems to be followed - except for no AV on the 30th pass or subsequently.

1
What is the exact message you're seeing in the AV, including the memory addresses? I find it hard to believe there's any correlation between certain emails being displayed in Chrome and the AV. Does it also happen with those emails being displayed and a new, blank VCL forms application? Or a new VCL forms application with a main form containing no code or controls that inherits from the same base form? I think you're also off-base about SysGetMem being involved; I think the issue is before that point and is just being raised in SysGetMem because of memory corruption before then.Ken White
(continued) I base that on System.Classes.TReader.ReadComponent(nil) prior to that - under what circumstances would you expect ReadComponent to be called with an argument of nil? Does anything in your main form attach to anything in the datamodule (e.g., a data-aware control)? Typically the datamodule needs to be created before the main form in the .dpr; it won't affect the assignment of TApplication.MainForm, because a datamodule can't be a main form.Ken White
What anti-virus software do you use and do you still get the behaviour if you turn it off? I have seen a similar problem recently, fixed by excluding my Delphi projects directory from where the AV monitors.MartynA
A lot happens before the dpr code. All the unit initializationDavid Heffernan
You say: If I step the program in debug mode within the IDE when the error is active. Before you step, you have just been notified about an AV. That is the first and most important info, that you still have not reveled, altough @Ken already asked for it. What is the complete message, including the addresses? Secondly, still before stepping anywhere, what does the call stack look like? What component is it loading? You know, you can double click any line in the call stack and it will take you to the corresponding source code. Put breakpoints on the previous lines at selected points for trace.Tom Brunberg

1 Answers

1
votes

I have narrowed the problem down to DevExpress's dxSpreadSheetCore unit. If I include that in any Uses clause, the error is displayed; if I omit it, no error. I have submitted the problem to DevExpress, although I was not able to simplify my application enough to also give them a useful demonstration of the error.

My assumption, based on comments here, is that something in the initialization section of dxSpreadSheetCore (or in its dependant units) is causing heap corruption.