Search code examples
delphiwindows-8esentedb

Esent crashes with Windows 8 on a Delphi project


I've been using ESENT for my projects quite extensively and I really love how easy and fast it works. And stable too!!

But I have a HUGE problem with Windows 8!!! Regardless of how I link to the esent.dll (dynamically or statically) whenever I call something other than JetSetSystemParameter, the dll is crashing, takig my app down the cliff.

Unfortunately I still can't get it running. My code had no problem running with Windows 7 or older. But with Windows 8 I get esent.dll crashing when I try to create an instance (floating point invalid operation).

I tried all possible calling conventions. This is definitely NOT the problem. I tried some more and discovered this weird situation: 1. I created a demo application using VS 2012 and JetCreateInstance worked just fine. 2. Exactly the same code in Delphi XE3 will send esent.dll crashing. 3. I created a DLL using VS 2012, exporting the method that worked perfectly in the above demo app, thinking it's a Delphi bug. 4. And then I loaded the DLL in a demo Delphi project (tried with 6, XE2 and XE3). Called the method and BOOM. Same crash.

Now my assumption is that Microsoft won't allow?!? any other developer environment to work correctly with the esent.dll. Is this possible???


Solution

  • The error, a floating point invalid operation, makes the problem sound as though it is related to the floating point control word.

    By default Delphi unmasks floating point exceptions. So when code asks the floating point unit to perform operations that result in errors, the FPU signals which is then converted to an exception.

    But most other Windows development environments mask these exceptions on the FPU. Such code is written under the assumption that the execution environment has FPU exceptions masked. But if you call a DLL from Delphi, the execution environment will have unmasked FPU exceptions, breaking that assumption. I suspect that if you mask FPU exceptions then your problems will disappear.

    To test if this is the problem, you can simply add this to your code, executed early in its life:

    Set8087CW($027F);
    

    This will mask all exceptions and set the FPU control word to the default Windows setting.

    In the longer term you may wish to mask exceptions before each call to this DLL, and then restore the FPU control word when the call to the DLL returns.

    That is a slightly dangerous game using the libraries that are supplied with Delphi since Set8087CW is not threadsafe due to its use of the global variable Default8087CW. If you wish to read more about that issue, I refer you to QC#107411.