Мы переносим нашу кодовую базу из BDS2006 в Rad Studio XE, и мы обнаружили очень странное поведение: если мы делаем недопустимую операцию с плавающей запятой (т.е. деление на ноль) после создания какого-либо объекта из COM-сервера, реализованного в .Net4.0 , мы не получаем нормальное исключение (т.е. EDivisionByZero), но EStackOverflow.
Нам удалось подготовить очень простой пример: ComErrorExample
Существует сборка .net 4.0 с com-интерфейсом (одна функция возвращает строку) и простым приложением delphi:
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's 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.
Как видите, мы делаем два деления на ноль - первое, перед созданием com-объекта, выбрасывает EDivisionByZero, второе - EStackOverflow.
Мы протестировали это на win7 x64 и winXP x32 - без разницы. Но когда мы переключили com сервер с .net4.0 на .net3.5 - все работает нормально.
Вопрос: мы делаем что-то не так? Можем ли мы что-то сделать, чтобы решить эту проблему?
Переключение на .net3.5 или сброс Delphi для нас не вариант.
UPDATE:
Мы проверяли конфигурацию с плавающей запятой (Set8087CW ()) раньше, но безуспешно.
ОБНОВЛЕНИЕ2: Я расширил пример с восстановлением конфигурации с плавающей запятой.