Accessing a public ini file while in crash
Accessing a public ini file while in crash
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?
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?
Re: Accessing a public ini file while in crash
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.
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.
Re: Accessing a public ini file while in crash
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?
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?
Re: Accessing a public ini file while in crash
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?
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?
Re: Accessing a public ini file while in crash
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?
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?
Re: Accessing a public ini file while in crash
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)
Re: Accessing a public ini file while in crash
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?
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?
Re: Accessing a public ini file while in crash
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.
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.
Re: Accessing a public ini file while in crash
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:
Leave all other code unchanged. Then add a new function like this:
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.
The solution to this is relatively easy: Modify your RegisterExceptionHandler code like this:
Code: Select all
RegisterExceptionHandler(@GlobalFrmMainExceptionFilter, stTrySyncCallOnSuccess);
Code: Select all
procedure GlobalFrmMainExceptionFilter(exceptIntf: IMEException; var handled: boolean);
begin
if frmMain <> nil then
frmMain.ExceptionFilter(exceptIntf, handled);
end;
Re: Accessing a public ini file while in crash
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?
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?
Re: Accessing a public ini file while in crash
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".
Re: Accessing a public ini file while in crash
Another solution would be to make iniSettings a global variable so I did this and now it works
Thanks!
Thanks!
Re: Accessing a public ini file while in crash
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.