|
This is not so much a bug as an incompatibility
between different compilers. There's a detailed explanation below. In
short, what happens is that Delphi and C++Builder set the control word
of the processor to a certain state, and applications or dlls written
in Visual C++, for example, set it to a different state. This causes crashes
(more precisely: floating point division by zero exceptions).
Luckily, there's a way around this. This problem can occur with every
math function in Delphi that sets the FPU (floating point unit) control
word. It's been reported to happen after a call to the Trunc function
by Joerg Stelkens (www.stelkens.de).
So it might be a good idea to apply the workaround described below at
the end of the GetParameter function too.
While browsing the Delphi 5 help file, I noticed a topic titled "Changes
to DLL initialization code". It explains this problem as well and states
that it shouldn't occur anymore when you make a dll in Delphi 5 or newer.
I haven't verified this, but if it's true, it's good news.
--- Workaround ---
If you're going to make a host program that loads plugins
that were created with another compiler, or if you're making plugins that
are going to be loaded by hosts that were created with another compiler,
you might want to include the workaround in your code. If you're using
the Delphi VST sdk 2.0.1 or higher or any 1.x version from 1.14, this
fix has been included in the sdk, so you don't need to worry about it
if you're making plugins. Below are some code fragments that solve the
problem. Be sure to call it during construction of a plugin (if you're
making a plugin) or right after you load a plugin (if you're making a
host app).
C++Builder
#include "float.h";
void secureFpu() {
_control87(PC_64|MCW_EM,MCW_PC|MCW_EM);
}
Delphi 3 or higher
procedure SecureFpu;
begin
Set8087CW(Default8087CW or $3F);
end;
Delphi 2 - The Set8087CW procedure wasn't available in
Delphi 2 yet. I once created a version of it, which I should still have
somewhere. If you're using Delphi 2 to create VST plugins, let me know and
I'll try to find it and mail it.
--- Explanation ---
This explanation has been provided by Frank Olbrich on
24 July 1998.
If VST starts, the CW is set to something like $XX3F (all FPU exceptions
off) => Everything works fine. But if you load a Borland DLL PLUGIN the
following steps occur:
1. the initialization part of system.pas calls _FpuInit.
2. _FpuInit is: asm FNINIT FWAIT FLDCW Default8087CW end;
3. The default value of Default8087CW is $1332 !!!!!!!!!!!!!
4. From now on the exceptions IE, ZE, OE can occur, because the operation
system only saves the state of the FPU if you switch to another task.
But the plugin is a dll and belongs to the VST-task. Therefore our dll
overrides the CW of VST.
5. If you turn a knob, a VST function divides by zero and raises a ZE
exception. =>
The solution is to set the loword of CW to its old value. I saw that you
fixed it with "OR $013F", but the hiword of CW has nothing to do with
exceptions (see table below). You set Bit 8 to value 1, that is dangerous
in one case. Bit 8 and 9 is the precision control of the FPU with the
following values: 00 : single precision 01 : reserved 10 : double precision
11 : extended precision
Normal case: dll is loaded (_FpuInit is called) CW is Default8087CW =
$1332 => your constructor calls SetFPU => CW is Default8087CW or $013F
= $133F => extended precision (11) => everything works fine, but...
Dangerous case: => dll is loaded (_FpuInit is called) CW is Default8087CW
= $1332 => a function, method or constructor is called that sets the precision
control to single precision => CW is $1032 => your constructor calls SetFPU
=> CW is $1032 or $013F = $113F => leads to an undefined state of the
precision control (01 see above) Therefore throw the 1 away and everything
is ok.
Table of the control word bits:
0: IM invalid operation mask
1: DM denormalized operand mask
2: ZM divide by zero mask
3: OM overflow mask
4: UM underflow mask
5: PM precision, inexact mask
6,7: reserved
8,9: PC precision control
10,11: RC rounding control
12..15 : |
|
|
|