Re: Oh boy, how did we miss this...

From: Rob Kennedy (me3_at_privacy.net)
Date: 11/02/04


Date: Tue, 02 Nov 2004 11:26:14 -0600

L D Blake wrote:
> Ok gang, here's a little tidbit we missed in all our SEH debate...

What you mean "we," Paleface?

> This is what Delphi (etc.) put on the stack when an exception guard frame is
> created...
>
> PExcFrame = ^TExcFrame;
> TExcFrame = record
> next: PExcFrame;
> desc: PExcDesc;
> hEBP: Pointer;
> case Integer of
> 0: ( );
> 1: ( ConstructedObject: Pointer );
> 2: ( SelfOfMethod: Pointer );
> end;
>
> When it's putting a try block Integer = 0 and it puts only the first part of
> the record.
>
> BUT it also uses exception frames to create Objects... if integer=1 the guard
> frame also stores a pointer to the Object, itself.

I wouldn't say it uses exception frames "to create objects"; rather, I'd
say it uses exception frames "while creating objects."

> The desc entry also has dual purpose. In SEH guard frames it points to the
> exception handler. In object guard frames it points to a jump instruction
> that leaps to some mysterious address...

The mysterious address is a label within the ClassCreate function.
ClassCreate gets called by the outermost constructor in an object
hierarchy. It calls NewInstance and InitInstance, and then it creates a
guard frame. There is only one guard frame per instance, so calling an
inherited constructor does not establish additional guard frames. (More
importantly, inherited constructors don't trigger additional calls to
NewInstance and InitInstance, but that's another kettle of fish.)

The guard frame is necessary because of one of the language's documented
requirements for objects: When an exception occurs within a constructor
and does not get completely handled, the object's destructor gets called
automatically to destroy the object. (The exception then continues to
propagate to the code that called the constructor.)

The extra field in TExcFrame is to hold the reference to the object so
ClassCreate's exception handler can pass it to the destructor. It needs
to be there because unlike in most Delphi exception handlers, the
handling code is not within the same scope as the "try" block. The
exception handler isn't guaranteed to have the object reference in any
particular register or in any particular stack location when the
exception occurs, so it just passes the needed information in the
exception frame. The layout of the exception frame was designed with
this kind of extensibility in mind.

The ConstructedObject field is only used in the constructor's exception
frame, not in any other circumstances. Likewise, the SelfOfMethod field
is only used in the exception handler inserted to wrap the
implementations of safecall methods (since HandleAutoException needs to
call the object's virtual SafeCallException method).

> They're actually using guard frames as object reference counters!

Object references? Yes. Counters? No. Objects aren't reference-counted.
(TInterfacedObject is reference-counted, but that's done without any
assistance from the compiler and without any specific regard to
exception handling. It's done to ensure that the object doesn't
inadvertantly destroy itself within its constructor.)

> So unwinding
> objects is the same as unwinding exceptions... hense all the object references
> in _handleanyexception ... It also helps destroy objects. It's not done as a
> true exception, in this case it's entered programatically by Delphi itself.

The only object references in HandleAnyException are the exception
objects (usually descendants of SysUtils.Exception). HandleAnyException
never knows when it's called in response to a constructor exception.
That's done implicitly by the address stored in TExcFrame.desc.

-- 
Rob


Relevant Pages

  • RE: Explorer errors
    ... The stored exception information can be accessed via .ecxr. ... Frame IP not in any known module. ... Also it could be the work of Add-Ons so try to clean up and disable ... Click on General Tab and you will see a Button called ...
    (microsoft.public.windowsxp.help_and_support)
  • RE: Explorer errors
    ... Download memtest from here: ... User Mini Dump File: Only registers, stack and portions of memory are ... The stored exception information can be accessed via .ecxr. ... Frame IP not in any known module. ...
    (microsoft.public.windowsxp.help_and_support)
  • Re: program not displaying frame
    ... > exception, etc., for what that's worth. ... > produces an error and then does in fact show a frame. ... of the enclosing class (in this case, it has default access scope). ... For my JVM on Windows 2003, it simply runs fine, ...
    (comp.lang.java.help)
  • RE: Explorer errors
    ... Thanks for your reply Nass. ... User Mini Dump File: Only registers, stack and portions of memory are ... The stored exception information can be accessed via .ecxr. ... Frame IP not in any known module. ...
    (microsoft.public.windowsxp.help_and_support)
  • overriding exception message
    ... I wanted to create an exception handler for certain processing I do - but ... although I can 'throw' to the constructor with a parameter, ... override the exception message property, the error says its read only. ...
    (microsoft.public.dotnet.languages.csharp)