【发布时间】:2013-11-01 14:13:39
【问题描述】:
我正在尝试在使用 Embarcadero C++ Builder 2010 编写的程序中使用 Intel's MKL library 中的一些函数。我遇到了一些奇怪的行为,即调用任何一种 MKL 方法都会静默终止应用程序。事实证明,当调用任何方法时,库正在调用TerminateProcess()。我在找到应用程序终止的确切位置时遇到了一些麻烦,因为每次进入 MKL 方法并在 CPU 视图中逐条指令跟踪都会在不同位置调用 TerminateProcess 方法。
我的猜测是,这是库捕获的错误情况。据我所知,它是从 MKL 库中调用的,而不是从任何库中调用的RTL 的其他部分或外部错误例程或其他任何地方。
什么可能导致这种情况?有没有人成功地将 MKL 与 C++Builder 程序一起使用?
症状
我有以下代码,基于Two-dimensional FFT (C Interface) 示例:
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);
调用DftiCreateDescriptor 时,该程序似乎消失了,没有被调试器捕获。因此,为了进行调查,我踏入了功能并走过了大会。它跳转到MKL_RT.DftiCreateDescriptor_s_md,然后我可以翻阅十页或更多页的程序集。在某些时候,它会call 一个原来是TerminateProcess 的地址。但是,它执行此操作的点感觉是随机的。例如,在某一时刻,我将它缩小到一个调用语句和地址,只是在我下次运行程序时它崩溃了。 编辑: 自从我第一次问这个问题后,我在ExitProcess、TerminateProcess、TerminateThread等处放置了断点,发现它正在调用TerminateProcess。 (最初我不知道它为什么会无声地终止。)它这样做的点仍然在变化。没有有用的调用栈(这是测试程序,源码如下):
: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
(这两个 MKL_RT.dll 行,在 CPU 视图中检查时,似乎没有使用正确的方法。这可能是因为它是发布代码并且调试器没有正确跟踪调用堆栈。. . 或者它可能与问题有关。)
我也用其他几种 MKL 方法重现了这一点。使用FFTW3 compatibility interface,有时会发生调用fftwf_malloc(有时不会),并且总是在调用fftwf_plan_dft_2d 时发生。
更多详情
- 我使用的是最新版本,2013 SP1。我只安装了 IA32 组件(因为 CB2010 是一个仅限 32 位的编译器。)
- 我正在链接single-DLL linking option,链接到
mkl_rt.dll。 - 但是,由于 mkl_rt.lib 是一个 COFF 文件,我使用
implib -a mkl_rt.lib mkl_rt.dll生成了一个新的 .lib。它创建了一个看起来不错的库,尽管警告了数百个重复符号。 - 下面的评论者greatwolf 建议使用不同的
implib命令implib -a -c mkl_rt.lib mkl_rt.dll,以保留方法名称大小写。这导致更少的重复名称警告,但不会链接:[ILINK32 Error] Fatal: Exceeded memory limit for block Import symbols in module _vsrnggumbel - 我还尝试动态加载库和函数,以防 .lib 文件、方法原型等出现问题(例如,从 DLL 加载和直接调用
DftiCreateDescriptor_s_md。)行为没有改变。 -
C interface for the DLL uses
cdeclcalling convention,这是项目选项设置为默认使用的内容,然后进入方法的调用代码,我看到所有参数都被压入堆栈。每个函数似乎都被正确调用了。 - 将我的动态加载原型更改为
stdcall(即使它应该找到cdecl版本)导致了同样的问题 - 但值得检查。 The DLL, mkl_rt.dll, supports mostly only thecdeclversions. - IDE 未设置为忽略任何异常。在 Tools > Options > Debugger Options > Embarcadero Debuggers > Native OS Exceptions 部分中,所有异常都设置为由调试器处理。
复制
这是一个简单的命令行 C 程序,足以演示崩溃:
#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;
}
IDE 用来构建它的 BCB 命令行是:
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
和链接:
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 , ,
我省略了大量的包含路径。为了完整起见,整行是:
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 文件 (x86)\Embarcadero\RAD Studio\7.0\include\boost_1_39\boost\tr1\tr1";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include\dinkumware";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include\vcl";"C:\Program Files (x86)\Embarcadero\RAD Studio\7.0\include\boost_1_39";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include\vcl";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\ObjRepos\Cpp";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include\Indy10";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Virtual Treeview\Common";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Virtual Treeview\Source";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Virtual Treeview\Delphi";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\include\boost_1_39";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Toolbar2000\TB2K\Lib\D12";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Toolbar2000\SpTBXLib\Source";"c:\program 文件 (x86)\embarcadero\rad 工作室\7.0\AutomatedQADocking\Source";"C:\Program Files (x86)\TMS 高级多边形列表";"C:\Program Files (x86)\TMS Advanced Poly List\Builder2010";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"c:\程序文件 (x86)\embarcadero\rad 工作室\7.0\缩写\源"-y -Q -k -r- -c -tWC -C8 -oDebug\mkltest.obj -w-par -Od -v -vi- -H=Debug\MKLTest.pch -H mkltest.c
和链接:
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 文件 (x86)\embarcadero\rad studio\7.0\lib";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\obj";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\psdk";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"c:\程序文件 (x86)\embarcadero\rad studio\7.0\lib";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\psdk";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\Indy10";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Toolbar2000\TB2K\Lib\D12";"c:\program 文件 (x86)\embarcadero\rad 工作室\7.0\AutomatedQADocking\Source";"C:\Program Files (x86)\TMS 高级多边形列表";"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 文件 (x86)\embarcadero\rad studio\7.0\lib";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\obj";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\psdk";"C:\Program Files (x86)\EurekaLab\EurekaLog 6\CBuilder14";"c:\程序文件 (x86)\embarcadero\rad studio\7.0\lib";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\psdk";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\lib\Indy10";"c:\program 文件 (x86)\embarcadero\rad studio\7.0\Toolbar2000\TB2K\Lib\D12";"c:\program 文件 (x86)\embarcadero\rad 工作室\7.0\AutomatedQADocking\Source";"C:\Program Files (x86)\TMS 高级多边形列表";"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 , ,
最后说明:我刚刚添加了 [delphi] 标签,因为它使用相同的 RTL,以防万一。我正在使用 RAD Studio 2010,它包括 C++ Builder 和 Delphi。我将 MKL 放入的主要应用程序是用两种语言编写的。上面的测试应用是纯C的。
【问题讨论】:
-
我没有安装 MKL 的 atm 来重现此问题,但您可以探索的途径是查看 msvc 或 mingw 是否也会发生这种情况。如果没有崩溃,你可以破解打开他们编译的反汇编,看看区别在哪里。也许在通话期间 borland 没有遵循一些约定?
-
为了完整起见,您是否还可以包含用于编译测试用例的
bcc32命令? -
@greatwolf,我添加了 bcc32 命令行。另外,我目前没有安装 MSVC 或 mingw,并且现在正在通过系留移动设备使用互联网 - 可能在我获得适当的互联网之前几天很难安装它们,抱歉.
-
我首先使用
impdef mkl.def mkl_rt.dll之类的东西创建了 def 文件。然后我删除了所有stdcall装饰函数(带有@xx后缀),然后是implib -a -c mkl.lib mkl.def。 -
我已将其发布到gist。
标签: c++ delphi c++builder intel-mkl c++builder-2010