Tuesday, May 15, 2007

Oh Borland, oh Microsoft, oh boy

What a wonderful world would it be, if you could develop your applications just on a single frameworks. Reality looks different. Me and many others need to cope with applications constructed from MSVC + or - MFC, VB6, Borland C++ and/or Delphi and other frameworks.
At first it looks like there is a more or less seamless integration possible. Later you discover all those little nasty glitches. In this post I will cover one of those glitches I really didn't know how to solve it but were I finally found a strange solution which I want to share.

To demonstrate the problem create a small C# application like this:



namespace CLRvsBorland
{
static class Program
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr LoadLibrary(string lpFileName);
static void Main()
{
IntPtr res = LoadLibrary(@"CC3250MT.DLL");
//try
//{

//// Throw an exception..

//throw new Exception();

//}

//catch

//{

//// .. and just catch it

//}


Double a1 = Double.NaN;
MessageBox.Show("Doh" + a1.CompareTo(Double.NaN).ToString());
}
}
}


When you start it in the debugger, you will get the following exception at instruction 'a1.CompareTo(Double.NaN)':

System.ArithmeticException was unhandled
Message="Overflow or underflow in the arithmetic operation."
Source="mscorlib"
StackTrace:
at System.Double.CompareTo(Double value)
[...]
at System.Threading.ThreadHelper.ThreadStart()


Now remove the comments - and surprise - it works!

I don't know, how it works. I assume it has to do with the order of jit-ing.
Explanations are highly wellcome ;-)

Update: Explanation found! Please have a look into the first 2 comments.

2 comments:

Unknown said...

This isn't just yet another case of the famous "Borland's Runtime Library changed my FPU Control Word"?

See for instance: http://www.virtualdub.org/blog/pivot/entry.php?id=53

Volker von Einem said...

Yeah! That's it!

I created a small managed C++ console application like that:

LoadLibrary(L"CC3250MT.DLL");
_control87(MCW_EM, MCW_EM);

System::Double^ a1 = System::Double::NaN;

Console::WriteLine(L"Doh: {0}",a1->CompareTo(System::Double::NaN).ToString());
return 0;

...and it works...
Thanks a lot!

Here's a blog post about how to fix this in borland or c#:
http://www.atomic14.co.uk/blog/archives/50