Wrong exception after calling .net4.0 com server from delphi application

We are moving our code base from BDS2006 to Rad Studio XE, and we found a very strange behavior: if we did an invalid floating point operation (i.e. division by zero) after creating some object from the COM server embedded in. Net4.0, we do not get a normal exception (i.e. EDivisionByZero), but EStackOverflow.

We were able to prepare a very simple example: ComErrorExample

There is a .net 4.0 assembly with a com interface (one function return function) and a simple delphi application:

var a, b: Double; Stored8087CW: Word; begin CoInitialize(nil); try b := 0; a := 1 / b; except on E: Exception do Writeln(E.ClassName, ': ', E.Message, ' (Expected type of exception)'); end; Stored8087CW := Get8087CW; Writeln('Code from .NET COM: ', CoExampleOfCOM.Create.DoSomething); Set8087CW(Stored8087CW); //it only to show that 8087 control word doesn't change try b := 0; a := 1 / b; except on E: Exception do Writeln(E.ClassName, ': ', E.Message, ' (Unexpected type of exception! Why stack overflow?)'); end; Readln; CoUninitialize; end. 

As you can see, we do two divisions by zero - first, one, before creating a com-object, throws EDivisionByZero, the second calls EStackOverflow.

We tested this on win7 x64, and winXp x32 - no difference. But when we switched the com server from .net4.0 to .net3.5, everything worked fine.

Question: are we doing something wrong? Can we do something to fix this problem?

Switching to .net3.5 or resetting Delphi is not an option for us.

UPDATE: We checked the floating point configuration (Set8087CW ()), but with no luck. UPDATE2: I have expanded the floating-point reconfiguration example.

+4
source share
2 answers

It looks like something in the COM-DLL is changing the configuration of the floating point processor. See Default8087CW and Set8087CW in Delphi Help.

You can save it before doing anything using the COM DLL and subsequently restore it.

 var Saved8087CW: Word; begin Saved8087CW := Default8087CW; // If you want, disable all fpu exceptions // with the next line. Set8087CW($133F); DoYourComOperationHere; Set8087CW(Saved8087CW); end; 
+2
source

I can not comment on the original question, so I'm sorry this answer, which is more likely a set of questions. Have you ever found an acceptable job on this? Have you logged a Delphi issue with Quality Central, and if you have an incident number?

I see that I think this is a related issue where on the Delphi side I set the CW FPU to $ 133f and then on the C # side I had

  try { Double.IsNaN(Double.NaN); } catch (ArithmeticException) { /* Intentionally empty. .NET will initialise the FPU at this point. */ } 

Which usually works in the 2.0 Framework, but now I get a huge amount of 0xC0000092: Checking the floating point stack. and then StackOverflow exceptions.

Adding the above code to public COM methods calls the call stack

 clr.dll!CLRVectoredExceptionHandlerShim() + 0xa3 bytes ntdll.dll!_RtlpCallVectoredHandlers@12 () - 0xef1c bytes ntdll.dll!_RtlCallVectoredExceptionHandlers@8 () + 0x12 bytes ntdll.dll!_RtlDispatchException@8 () + 0x19 bytes ntdll.dll!_KiUserExceptionDispatcher@8 () + 0xf bytes clr.dll!CLRVectoredExceptionHandler() + 0x9a bytes clr.dll!CLRVectoredExceptionHandlerShim() + 0xa3 bytes 
+1
source

Source: https://habr.com/ru/post/1340965/


All Articles