BUG: Jet's Visual Basic Expression Service (Expsrv.dll) Changes FPU Precision to 64 Bits (308702)
The information in this article applies to:
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft OLE DB Provider for Jet 3.51
- Microsoft OLE DB Provider for Jet 4.0
- The C Run-Time (CRT)
- The Microsoft Foundation Classes (MFC)
This article was previously published under Q308702 SYMPTOMS
When you use a Microsoft Jet SQL query with a Visual Basic for Applications (VBA) expression in it, the floating point unit (FPU) precision of an application may be changed to 64 bits. For example, the SQL statement might resemble the following:
Select Left([City],4) AS MyCity FROM Customers
CAUSE
Most applications that are built with the C/C++ Run-time Library or with Microsoft Visual Basic use the default 53-bit precision. However, when using Jet queries you may find that the precision changes to 64 bits.
Expsrv.dll internally implements its own InitFP() function. This function calls the FPU's FNINIT function, which changes the precision to 64 bits. InitFP() is called at the initialization of the VBA expression service. The initialization occurs when you first use a VBA-intrinsic function in a SQL statement. If your application does not maintain a default workspace (for instance, an open connection handle), InitFP is called each time that a connection is made to the database. InitFP is also called when an exception occurs.
RESOLUTION
To work around this problem, write your application to set FPU precision values when needed.
For example, assume that you have a function which requires 53-bit precision (doing some flointing point calls in the C runtime). You can change the precision at the beginning of a function and then change it back at the end of the scope of your function. To do this, you can write a helper C++ class that sets the FPU precision on construction and resets it on destruction; for example:
class C53Precision
{
DWORD m_dwOldPrecision;
public:
C53Precision(){
m_dwOldPrecision= _controlfp(0,0)&_MCW_PC;
_controlfp(_PC_53, _MCW_PC);
}
~C53Precision(){_controlfp(m_dwOldPrecision, _MCW_PC); }
};
The class constructor changes the precision to 53 bits, and the destructor changes it back to the original precision.
Alternatively, because only Jet database calls which use VBA built-in functions change the FPU precision, you can change the precision after those Jet calls; for example:
CRecordset rs(&db);
rs.Open(CDatabase::dbDynaset, szSQL);
_controlfp(_PC_53, _MCW_PC); //Change the precision back to 53 bits.
For Visual C++ developers, another alternative is to use 64-bit precision thoughout your application. You can do this by linking to fp10.obj, which changes CRT's precision to 64 bits.
STATUSMicrosoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.
Modification Type: | Minor | Last Reviewed: | 9/26/2005 |
---|
Keywords: | kbHotfixServer kbQFE kbbug KB308702 |
---|
|