NEWS | VST | ASIO | DELPHI TIPS | WEBOS | LINKS | ABOUT ME
                                
             
 

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 :

 
 
         
 
 
Copyright © 2003-2013 Frederic Vanmol. All rights reserved.