typical madexcept usage in a c++ dll

delphi package - automated exception handling
Post Reply
christoph
Posts: 6
Joined: Thu Aug 24, 2017 8:03 am

typical madexcept usage in a c++ dll

Post by christoph »

Hi,

I am evaluating madexcept and have perfect results in c++ applications up to now.
Now, I am trying to check usage in c++ DLLs, starting from the point that *the application itself will not be compiled with madexcept*, instead only the DLL (my DLL) will have madexcept embeddet.
After a bit of try-and-error and reading forum entries/delphi documentations, I found out that one approach is to make a try..catch wrapper in the dll, where some forum entries suggested different syntaxes.


1)
I now tested with three variants, can you *please* tell me if it doesn't care what variant I use or if there is a "suggested" or "better" variant?

Code: Select all

  __try{
    // call the real code
  }
  __except(EXCEPTION_EXECUTE_HANDLER){
    Madexcept::HandleException();
  };

Code: Select all

  try{
    // call the real code
  }
  catch (...)
    Madexcept::HandleException();
  };

Code: Select all

  try{
    // call the real code
  }
  catch (Exception &excObj){
    Madexcept::HandleException(etNormal, &excObj);
  };
To me, all three variants seem to work, but, again, I do not now what is the suggested way of doing it.


2)
By using any of the three variants above, I can catch all exceptions in the "normal" call stack of the DLL code.
I seem not to be able to catch an exception thrown inside the GUI thread, though.
Example: I added a on button click event function, and inside that function I programmatically generate a division by zero exception.
When I click the button, the division by zero is catched by someone else (probably the main application), with a "simple" messagebox.

3)
And a last question, trying to solve issue #2 by myself I was wondering if it might help, in my DLL Entry Initialization routine, to (globally?) register the madexcept exception handler, so calling RegisterExceptionHandler() somehow.
I did not manage to do that, though, mostly because the example is in delphi and I did not manage to map that to c++ correctly, but even then, I am not even sure if this approach would help.


So I hope anybody can give me a hint into the right direction.
The task to be achieved is that I'd like to have all exceptions happening inside my DLL functions catched by madexcept, even tough the main application is not madexcept aware.

Thanks ahead for any hints!
Regards

Christoph
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: typical madexcept usage in a c++ dll

Post by madshi »

I don't think madExcept cares which of the 3 try..xxx versions you're using. I'm not really all that great of a BCB expert, though, so it wouldn't hurt to try all 3 and check which works best. Since you already seem to have done that and found no differences, I'd suggest to go with the "lowest level" one, the __try..__except, because it should catch really all type of crashes while the others might be limited to catching only specific exceptions.

About #2 and #3 I'm slightly confused. You seem to want to catch exceptions when a button in the EXE is pressed (?), but then you say you want to catch exceptions that happen inside of the DLL. That seems to contradict each other?
christoph
Posts: 6
Joined: Thu Aug 24, 2017 8:03 am

Re: typical madexcept usage in a c++ dll

Post by christoph »

Sorry, I might not have been clear enough.
The call stack is as following:

EXE (without madexcept) -> calls one generic DLL function (with madexcept) -> this function has a try..catch with madexcept -> and inside the try calls the real payload
Now:

Use-Case 1.
The real payload of the DLL Function executes a load of methods, inside the callstack I can throw a divbyzero exception (testcase) anywhere, the try..catch in the dll function will catch it and display the madexcept dialog.
All is fine.

Use-Case 2.
The real payload of the DLL Function executes a load of methods, and somewhere displays a dialog form in modal way. A random button on the dialog form has a onClick() event. In the onclick() event I do issue a divbyzero exception. Now, the divbyzeroexception is *not* catched by the try..catch of the dll function (even tough, tecnically, we are almost inside the call stack, the only difference being is that dialog.showModal() will probably work in a separate thread, the gui thread...)

I hope this is clearer now.
It seems like exceptions that happen in the "GUI Thread" are catched by the "application" or "default" exceptionhandler, the one that probably gets setup in the executable itself.
Since the DLL function calls a dialog.showmodal(), it seems to me that flow of control switches from the DLL execution stack to the gui thread execution stack, and that the exception there is not catched.

Is this a realistic assumption?
Do I have to live with this? Or would my (failed) approach of "registering" the "global" Exception Handler inside the DLL Entry Function be a way to go? Basically, overwriting the (default) exception handler...
But, again, I did non manage to do that, the syntactical sugar of the c++ generated headers files was not clear to me...

Thanks!
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: typical madexcept usage in a c++ dll

Post by madshi »

So your DLL contains the full VCL and shows its own windows? Or does the DLL link to the RTL and VCL runtime packages?
christoph
Posts: 6
Joined: Thu Aug 24, 2017 8:03 am

Re: typical madexcept usage in a c++ dll

Post by christoph »

Well, it does link to the RTL and VCL runtime packages but the windows shown are "own", in the sense that its VCL forms created/instantiated inside the dll.
So really, the call flow is probably:

main executable -> dll function -> try..catch..wrapper -> dll method(s) -> myowndialog.showmodal() -> RTL/VCL GUI Thread? -> User Interaction button.onclick() -> onclick_method inside the dll (but probably called from "outside" if the GUI thread is something "outside")

Would it make a difference if the RTL and VCL would be statically linked to the dll, instead of using the dynamic runtime packages?
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: typical madexcept usage in a c++ dll

Post by madshi »

Actually, if you use the dynamic RTL/VCL packages, that makes things a bit easier for madExcept. Does the main application also use the RTL and VCL? Or is it a non-Delphi/BCB application?
christoph
Posts: 6
Joined: Thu Aug 24, 2017 8:03 am

Re: typical madexcept usage in a c++ dll

Post by christoph »

The main application is a delphi application (out of my control scope).
The DLL is a c++-builder shared library.
RTL and VCL are shared.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: typical madexcept usage in a c++ dll

Post by madshi »

Ok, so normally in a process where EXE and DLL share the same dynamic RTL and VCL runtime packages, madExcept should automatically catch "everything", if you compile it into just one of the modules (exe or dlls). So the big question is why it doesn't seem to work in your specific case. To be honest, I'm not completely sure. Is it possible that the application itself might have the RTL and VCL linked into the EXE file instead of using the dynamic runtime packages? That would explain the problem.
christoph
Posts: 6
Joined: Thu Aug 24, 2017 8:03 am

Re: typical madexcept usage in a c++ dll

Post by christoph »

Hi,
and thanks for your support!

I understand the issue - maybe it is as you say, and the main application has rtl/vcl statically linked, I cannot tell for sure.
The distribution of the application contains rtl190.dll and vcl190.dll, so one would think that they are using it dynamically, but then, again, the app has many plugins (as my dll is one as well), so I cannot exclude that maybe the shared dll's are only used by the plugins, and the main app uses static versions. I can't exclude it, for now.
Thanks anyway for the explanations.

One last thing, then - using the try..catch clause in the dll method should *generally* be enough to correctly be using madexcept, as I read from your replies up to now.
Registering an (alternative or madexcept default) exception handler in the dll create method would not be of any help, right? The "exception handler" is something that will be called by madexcept once the exception is triggered.
But since, in my case, the exception in the gui thread is not detected by madexcept, the "exception handler" would not be called in any case. Did I get this correlation right?

Thanks!
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: typical madexcept usage in a c++ dll

Post by madshi »

Generally, exception handling works like this: Whenever an exception occurs, the crashing thread jumps into the nearest try..except block. And try..except blocks don't care at all about module (exe/dll) boundaries. Which means that for some reason the exception occurs in a code section which is protected by a try..except block, that specific try..except block is activated, and if that try..except block fully "handles" the exception, the exception will not be noticed from any code outside.

In your specific case, it seems that the exception is most probably happening somewhere where the exe has a try..except block around it. E.g. this could simply be the main message loop in the exe, which does have a try..except around it. Normally, madExcept hooks into this, but that only works if madExcept has access to the RTL/VCL which is running the main message loop. If the exe uses a different RTL/VCL instance, then madExcept has successfully hooked your own RTL/VCL instance, but not the one running in the exe.

There is a way to get access to *ALL* exceptions. You could ask to be notified about any exception in the whole process, before it's passed on to any try..except blocks. You could use this an then call madExcept for all exceptions. But if you do this, madExcept will show crash boxes even for exceptions that are not supposed to be visible. E.g. if you have code that might raise an expected exception somewhere, and you have a try..except block around it that is supposed to "hide" the exception, it would suddenly become visible. Which is usually not a good idea. So I don't recommend this approach. The best approach is to let madExcept only become active for unhandled exceptions, because those are the ones which are usually true "crashes". But then we run into the issue with different RTL/VCL instances...
christoph
Posts: 6
Joined: Thu Aug 24, 2017 8:03 am

Re: typical madexcept usage in a c++ dll

Post by christoph »

Hi,

thanks again - now I fully understand the flow. Yes, I assume what you depict as a possible reason (the main message loop in the exe) is the point. The upstream vendor of the main exe might have used a different rtl/vcl instance for the main application, I can think of a statically linked one, maybe they are also using an older one.

In any case, now that I know the inner workings, it's reasonable to accept the current situation. The exception I am trying to narrow down seems to be happening inside the dll thread, not in the gui thread, so I might be all set. I will see.

Thanks a lot!
Post Reply