Accessing a public ini file while in crash

delphi package - automated exception handling
Post Reply
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Accessing a public ini file while in crash

Post by emailaya »

I have iniSettings: TINIFile as public in my application.

in the initialization section I did the following:
initialization
RegisterExceptionHandler(frmMain.ExceptionFilter, stTrySyncCallOnSuccess);
madExcept.InstallUnhandledExceptionFilter();

In procedure TfrmMain.ExceptionFilter(const exceptIntf : IMEException; var Handled : Boolean);
I do the following:
res := iniSettings.ReadString('General','email','');
but inside this event, iniSettings is in "inaccesible value" state so I have an exception inside the event. After this, nothing happens and I can continue working as if nothing happened to the iniSettings variable, it seems to be obsolete only inside the event.

Any idea what am I missing?
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: Accessing a public ini file while in crash

Post by madshi »

Are you sure that the global "iniSettings" variable is really initialized/filled at the moment you access it from within your exception handler? Maybe the exception handler is called before you initialize "iniSettings", or after you finalize/destroy it?

Another possibility could be if there's an "iniSettings" local variable or class member/variable in TfrmMain? You could solve that by using "unitName.iniSettings" instead to clarify which one you mean.

One more potential issue is that your exception handler might be called in the context of a secondary thread. But as long as there's no other thread accessing "iniSettings" at the same time, that should not be a problem, I believe.
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Re: Accessing a public ini file while in crash

Post by emailaya »

I'm sorry but none of the above is relevant to my case:

I initialize iniSettings in FormCreate and do a lot of reading from it that works. The process that fails is after clicking a button after the form is already visible and running. iniSettings is destroyed in FormDestroy and I put a breakpoint there so I know it never reaches there when the exception occurs.

I define, create and destroy iniSettings in 3 specific places and I don't use this name anywhere else.

I don't use any threads whatsoever. I put a breakpoint in the finally clause of the failing part and there iniSettings shows a value, after the finally clause finishes, it "jumps" to ExceptionFilter where iniSettings becomes "inaccesible value", I get another Delphi exception that MadExcept doesn't catch (I don't mind that) and the application continues, then I go to a window that reads info from iniSettings and it works perfectly, then I close the application, FormDestroy destroys iniSettings as expected and the application closes.

Any other idea?
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: Accessing a public ini file while in crash

Post by madshi »

I suppose the "inaccessible" is an IDE debugger complaint, when trying to use the "Evaluate / Modify" window? If so, try turning off optimization.

Or is it also "inaccessible" outside of the IDE debugger? Do you get an exception when trying to access it? Or do you get bogus data or something?
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Re: Accessing a public ini file while in crash

Post by emailaya »

I get inaccessible in debug and when this line of code is executed (I put a break point and pressed F8) I get AV (that madexcept does not intercept but I don't mind about that).

I remind you that when an exception occurs, all variables are not accessible, only when the code reaches the finally, every thing is back to normal. Maybe exceptfilter is executed in between?
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Re: Accessing a public ini file while in crash

Post by emailaya »

Notice that iniSettings is defined as public of the main form class and exceptfilter (procedure that catches the exceptions) is also defined in frmMain class(don't remember if in public or private, I'm not near the relevant computer to check now)
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: Accessing a public ini file while in crash

Post by madshi »

Ok, I think I misunderstood what you wrote originally. I thought you had declared iniSettings as a global variable in your unit. But now I think you have it declared as a variable in your class, is that correct?

This "frmMain" variable is a global variable, right? Does this form get destroyed and recreated at some point in your application's life?

At the moment when you call RegisterExceptionHandler, is "frmMain" already initialized?
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Re: Accessing a public ini file while in crash

Post by emailaya »

iniSettings is public in frmMain class, so is exceptfilter that catches the exceptions, notice my code:

initialization
RegisterExceptionHandler(frmMain.ExceptionFilter, stTrySyncCallOnSuccess);
madExcept.InstallUnhandledExceptionFilter();

I guess that initialization clause is executed before frmMain is initialized (when the application starts) but when the exception occurs, frmMain is "alive" and the procedure is executed as expected (except for the iniSettings problem). frmMain is created automatically by the application and is destroyed when the application closes.
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: Accessing a public ini file while in crash

Post by madshi »

Ah, there we have the problem. When calling RegisterExceptionHandler remember the value that "frmMain" has at that moment and that value is then later used as "self", when calling your exception handler. So when you access "iniSettings" in your exception handler, really you're using "self.iniSettings" which in that situation ends up as "TfrmMain(nil).initSettings".

The solution to this is relatively easy: Modify your RegisterExceptionHandler code like this:

Code: Select all

RegisterExceptionHandler(@GlobalFrmMainExceptionFilter, stTrySyncCallOnSuccess);
Leave all other code unchanged. Then add a new function like this:

Code: Select all

procedure GlobalFrmMainExceptionFilter(exceptIntf: IMEException; var handled: boolean);
begin
  if frmMain <> nil then
    frmMain.ExceptionFilter(exceptIntf, handled);
end;
This way your code no longer uses the "frmMain" value at the time when you called RegisterExceptionHandler. Instead it will use the current value of the global "frmMain" variable.
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Re: Accessing a public ini file while in crash

Post by emailaya »

I will try it later when I'm near the computer but one question:
frmMain was nil when registering but it is not nil when the exception occurs so when the code executes, self is not nil at the moment so why it handles it as if it is still nil?
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: Accessing a public ini file while in crash

Post by madshi »

Passing "frmMain.ExceptionFilter" to RegisterExceptionHandler is interpreted by the compiler as passing two different parameters: "Self: pointer; methodAddress: pointer". So RegisterExceptionHandler gets two pointers, and one of them is "nil".
emailaya
Posts: 249
Joined: Thu Oct 13, 2005 11:33 am
Contact:

Re: Accessing a public ini file while in crash

Post by emailaya »

Another solution would be to make iniSettings a global variable so I did this and now it works
Thanks!
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Re: Accessing a public ini file while in crash

Post by madshi »

Yes, that works, too, but I would still recommend to use the solution I suggested. Why? Because if you ever try to access some other class method/function/variable in your "frmMain.ExceptionFilter" handler, you'll get a crash again. It makes no sense to have your exception handler inside of the class, if the "self" pointer is incorrect. If you don't want to change too much, simply make "ExceptionFilter" a global function instead of a class method, then at least there's no danger that you'll accidently run into the crash in the future again.
Post Reply