Tracking down Delphi “abstract error” occassions.
Posted by jpluimers on 2020/11/12
A few tips.
- Set breakpoints in these units:
- System.pas:
procedure _AbstractError; begin if Assigned(AbstractErrorProc) then AbstractErrorProc; RunErrorAt(210, ReturnAddress); end;
- System.SysUtils.pas:
procedure AbstractErrorHandler; begin raise EAbstractError.CreateRes(@SAbstractError); end;
- System.pas:
- add a watch for
ClassName
that has “Allow side effects and function calls” enabled - run your code until it breaks or stops (usually in the first method above)
- double click on each entry in the “Call Stack” pane, and for each entry:
- set a break point on the call to the method above it in the stack trace
- note that sometimes this is on the line you arrived, but sometimes one more more lines higher in your code
- the cause is that the stack trace will show you where your code will RETURN to, not the place it was CALLED FROM.
- abort your program
- run your program again
- on each hit breakpoint, watch the value of
ClassName
:- if it becomes [WayBack]
E2003: Undeclared identifier: 'ClassName'
, then:- observe the method directives
- if it includes
static
, but it is actually inside aclass
, then remove the static
- if it becomes [WayBack]
Sometimes you cannot perform the last step: class property
definitions have to be backed by static class methods.
This usually means you have a bad design anyway: you depend on global/singleton kind of behaviour that is almost impossible to properly test.
A better approach is to have regular object instances for that, then use constructor dependency injection (maybe combined with factory or dependency injection container) to setup the structures of dependencies.
TODO
Create a conference summary on the use of class versus instance methods, and static/regular.
Base materials:
- Workaround for Delphi 2010 compiler error “E2076 This form of method call only allowed for class methods” when it infers a generic parameter type.
- Delphi 2007: reproduction and workaround for “[DCC Error] ….pas(26): F2084 Internal Error: AV21BCE0AC-R00000000-0”
- Delphi class constructors and initialisation order
- Delphi analog to C# ?? null-coalescing operator and Light Table like debugger evaluation
- As Delphi generics are not supported for free functions, wrap them in a record container.
- Delphi: a pattern for a generic factory, this one for components, but can be uses for anything having a base class like a TThread descendant.
- How to convert a Delphi enum or set to a JSON value, with different specific values…
- Delphi: Why is there no class procedure TArray.Sort(Keys: array of T; var Values: array of T; const Comparer: IComparer);
- TInterlockedHelper for Delphi interfaces: Spring.Reactive.pas « The Wiert Corner – irregular stream of stuff
- Class methods in Record vs Class in Delphi 2010 – Stack Overflow
- E2398 Class methods in record types must be static (Delphi) – RAD Studio « The Wiert Corner – irregular stream of stuff
- Delphi static class methods are assignment compatible with plain old function pointers
–jeroen
Leave a comment