I am trying to use some functions from Intel's MKL library, in a program written with Embarcadero C++ Builder 2010. I'm running into some odd behaviour where calling any one of the MKL methods silently terminates the application. It turns out that the library is calling TerminateProcess()
when any method is called. I'm having some trouble finding exactly where the app terminates, because stepping into the MKL method and tracing instruction by instruction in the CPU view calls into the TerminateProcess
method at different places every time.
My guess is that this is an error condition caught by the library. As far as I can tell, it is called from within the MKL library, not from any other part of the RTL or an external error routine or anywhere else.
What might cause this? Has anyone successfully used the MKL with a C++Builder program?
Symptoms
I have the following code, based on the Two-dimensional FFT (C Interface) example:
DFTI_DESCRIPTOR_HANDLE hDesc;
MKL_LONG alDimensions[2];
alDimensions[0] = 32; // Array dimensions
alDimensions[1] = 100;
MKL_LONG lStatus = DftiCreateDescriptor(&hDesc, DFTI_SINGLE, DFTI_COMPLEX, 2, alDimensions);
The program appeared to vanish uncaught by the debugger when calling into DftiCreateDescriptor
. So, to investigate, I stepped into the function and walked through the assembly. It jumps to MKL_RT.DftiCreateDescriptor_s_md
, and then I can page through ten or more pages of assembly. At some point, it will call
an address that turns out to be TerminateProcess
. However, the point at which it does this feels random. At one point, for example, I narrowed it down to one call statement and address, only to have it crash before I got there next time I ran the program. Edit: Since I first asked this question, I placed breakpoints at ExitProcess
, TerminateProcess
, TerminateThread
, etc, and found that it is calling TerminateProcess
. (Originally I didn't know why it terminated silently.) The point at which it does so still changes. There is no useful call stack (this is the test program, source below):
:7540d79a kernel32.TerminateProcess
:5be911c9 ; C:\projects\mkl crash\Debug\MKL_RT.DLL
:5be837bd ; C:\projects\mkl crash\Debug\MKL_RT.DLL
:004013C5 main(argc=1, argv=:008B9908)
:32ad2342 ; C:\Windows\SysWOW64\CC32100.DLL
(Those two MKL_RT.dll lines, when examined in the CPU view, don't appear to be in the right methods. Chances are this is because it's release code and the debugger isn't tracing the call stack properly... or it could be related to the problem.)
I've reproduced this with several other MKL methods too. Using the FFTW3 compatibility interface, it sometimes occurs calling fftwf_malloc
(and sometimes doesn't), and always occurs when calling fftwf_plan_dft_2d
.
More details
- I am using the latest version, 2013 SP1. I installed only the IA32 components (since CB2010 is a 32-bit only compiler.)
- I am linking with the single-DLL linking option, linking to
mkl_rt.dll
. - However, since mkl_rt.lib is a COFF file, I generated a new .lib using
implib -a mkl_rt.lib mkl_rt.dll
. It created an apparently fine library, although warned about hundreds of duplicate symbols. - Commenter greatwolf below suggested a different
implib
command,implib -a -c mkl_rt.lib mkl_rt.dll
, to preserve method name case. This caused far fewer duplicate name warnings, but won't link:[ILINK32 Error] Fatal: Exceeded memory limit for block Import symbols in module _vsrnggumbel
- I have also tried loading the library and functions dynamically, in case there was a problem with the .lib file, method prototypes, etc (eg, loading and directly calling
DftiCreateDescriptor_s_md
from the DLL.) The behaviour is unchanged. - The C interface for the DLL uses
cdecl
calling convention, which is what the project options are set to use by default, and stepping into the calling code for a method I see all the parameters being pushed on the stack. Each function appears to be being called correctly. - Changing my dynamically loaded prototype to
stdcall
(even though it should be finding thecdecl
version) caused the same problem - but it was worth checking. The DLL, mkl_rt.dll, supports mostly only thecdecl
versions. - The IDE is not set to ignore any exceptions. In the Tools > Options > Debugger Options > Embarcadero Debuggers > Native OS Exceptions section, all exceptions are set to be handled by the debugger.
Reproducing
Here is a simple command-line C program that is enough to demonstrate the crash:
#include <stdio.h>
#pragma hdrstop
#include <tchar.h>
// Intel MLK
#include "mkl/include/mkl.h"
#pragma comment(lib, "mkl/mkl_rt.lib") // Generated with implib
int _tmain(int argc, _TCHAR* argv[]) {
DFTI_DESCRIPTOR_HANDLE hDesc;
MKL_LONG lStatus;
MKL_LONG alDimensions[2];
alDimensions[0] = 32;
alDimensions[1] = 100;
lStatus = DftiCreateDescriptor(&hDesc, DFTI_SINGLE, DFTI_COMPLEX, 2, alDimensions);
// Here, you would normal declare your arrays (32x100) of _Complex, and call DftiCommitDescriptor,
// DftiComputeForward, DftiFreeDescriptor - but it will have already terminated
// on the line above.
return 0;
}
The BCB command line the IDE builds this with is:
c:\program files (x86)\embarcadero\rad studio\7.0\bin\bcc32.exe -D_DEBUG -D_RTLDLL;_NO_VCL -I"..." -y -Q -k -r- -c -tWC -C8 -oDebug\mkltest.obj -w-par -Od -v -vi- -H=Debug\MKLTest.pch -H mkltest.c
and linking:
c:\program files (x86)\embarcadero\rad studio\7.0\bin\ilink32.exe -LDebug;"...";"..." -lDebug -v -G8 c0x32 Debug\mkltest.obj , Debug\MKLTest.exe , Debug\MKLTest.map , import32.lib cw32i.lib , ,
Where I omitted a huge number of include paths. For the same of completeness, the entire lines are:
c:\program files (x86)\embarcadero\rad studio\7.0\bin\bcc32.exe -D_DEBUG -D_RTLDLL;_NO_VCL -I"C:\Program Files (x86)\EurekaLab\EurekaLog 6\Cbuilder14";C:\projects\Misc\DirectX\Direct3D\Tutorials\Tut05_Textures;"C:\Program Files (x86)\Embarcadero\RAD Studio\7.0\include\boost_1_39\boost\tr1\tr1";"c:\program files (x86)\embarcadero\rad studio\7.0\include";"c:\program files (x86)\embarcadero\rad studio\7.0\include\dinkumware";"c:\program files (x86)\embarcadero\rad studio\7.0\include\vcl";"C:\Program Files (x86)\Embarcadero\RAD Studio\7.0\include\boost_1_39";"c:\program files (x86)\embarcadero\rad studio\7.0\include";"c:\program files (x86)\embarcadero\rad studio\7.0\include\vcl";"c:\program files (x86)\embarcadero\rad studio\7.0\ObjRepos\Cpp";"c:\program files (x86)\embarcadero\rad studio\7.0\include\Indy10";"c:\program files (x86)\embarcadero\rad studio\7.0\Virtual Treeview\Common";"c:\program files (x86)\embarcadero\rad studio\7.0\Virtual Treeview\Source";"c:\program files (x86)\embarcadero\rad studio\7.0\Virtual Treeview\Delphi";"c:\program files (x86)\embarcadero\rad studio\7.0\include\boost_1_39";"c:\program files (x86)\embarcadero\rad studio\7.0\Toolbar2000\TB2K\Lib\D12";"c:\program files (x86)\embarcadero\rad studio\7.0\Toolbar2000\SpTBXLib\Source";"c:\program files (x86)\embarcadero\rad studio\7.0\AutomatedQADocking\Source";"C:\Program Files (x86)\TMS Advanced Poly List";"C:\Program Files (x86)\TMS Advanced Poly List\Builder2010";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"c:\program files (x86)\embarcadero\rad studio\7.0\Abbrevia\source" -y -Q -k -r- -c -tWC -C8 -oDebug\mkltest.obj -w-par -Od -v -vi- -H=Debug\MKLTest.pch -H mkltest.c
and linking:
c:\program files (x86)\embarcadero\rad studio\7.0\bin\ilink32.exe -LDebug;"c:\program files (x86)\embarcadero\rad studio\7.0\lib\debug";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\Cbuilder14";C:\projects\Misc\DirectX\Direct3D\Tutorials\Tut05_Textures;"c:\program files (x86)\embarcadero\rad studio\7.0\lib";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\obj";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\psdk";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"c:\program files (x86)\embarcadero\rad studio\7.0\lib";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\psdk";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\Indy10";"c:\program files (x86)\embarcadero\rad studio\7.0\Toolbar2000\TB2K\Lib\D12";"c:\program files (x86)\embarcadero\rad studio\7.0\AutomatedQADocking\Source";"C:\Program Files (x86)\TMS Advanced Poly List";"C:\Program Files (x86)\TMS Advanced Poly List\Builder2010";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"C:\Users\Public\Documents\RAD Studio\7.0\DCP" -jDebug;"c:\program files (x86)\embarcadero\rad studio\7.0\lib\debug";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\Cbuilder14";C:\projects\Misc\DirectX\Direct3D\Tutorials\Tut05_Textures;"c:\program files (x86)\embarcadero\rad studio\7.0\lib";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\obj";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\psdk";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"c:\program files (x86)\embarcadero\rad studio\7.0\lib";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\psdk";"c:\program files (x86)\embarcadero\rad studio\7.0\lib\Indy10";"c:\program files (x86)\embarcadero\rad studio\7.0\Toolbar2000\TB2K\Lib\D12";"c:\program files (x86)\embarcadero\rad studio\7.0\AutomatedQADocking\Source";"C:\Program Files (x86)\TMS Advanced Poly List";"C:\Program Files (x86)\TMS Advanced Poly List\Builder2010";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"C:\Users\Public\Documents\RAD Studio\7.0\DCP" -lDebug -v -G8 c0x32 Debug\mkltest.obj , Debug\MKLTest.exe , Debug\MKLTest.map , import32.lib cw32i.lib , ,
Final note: I just added the [delphi] tag, since it uses the same RTL, in case that is related. I'm using RAD Studio 2010, which includes both C++ Builder and Delphi. The main app I'm putting the MKL into is written with both languages. The test app above is pure C.
bcc32
command used to compile the test case? – greatwolfimpdef mkl.def mkl_rt.dll
. Then I removed all thestdcall
decorated functions (with the@xx
suffix), following that withimplib -a -c mkl.lib mkl.def
. – greatwolf