调用标准C函数fprintf()时,用嵌入式R.dll编译的C程序崩溃
我正在使用MSVC2013更新5并从Revolution R 3.2.2 x64导入R.dll库,以编译使用embded R.dll的自定义版本Rserve()。CRT类型是多线程调试DLL。以一种非常奇怪的方式调用fprintf(stderr,…)时,程序崩溃:调用标准C函数fprintf()时,用嵌入式R.dll编译的C程序崩溃,c,r,dll,C,R,Dll,我正在使用MSVC2013更新5并从Revolution R 3.2.2 x64导入R.dll库,以编译使用embded R.dll的自定义版本Rserve()。CRT类型是多线程调试DLL。以一种非常奇怪的方式调用fprintf(stderr,…)时,程序崩溃: ntdll.dll!RtlRaiseStatus() Unknown ntdll.dll!string "Enabling heap debug options\n"() Unknown ntdll.dll!RtlEnterCri
ntdll.dll!RtlRaiseStatus() Unknown
ntdll.dll!string "Enabling heap debug options\n"() Unknown
ntdll.dll!RtlEnterCriticalSection() Unknown
msvcrt.dll!_lock_file() Unknown
msvcrt.dll!putc() Unknown
R.dll!000000006c8dd814() Unknown
R.dll!000000006c8df8e8() Unknown
R.dll!000000006c8e3d74() Unknown
R.dll!000000006c8dd00d() Unknown
RServe.exe!loadConfig(const char * fn) Line 2113 C
RServe.exe!main(int argc, char * * argv) Line 4247 C
[External Code]
代码如下所示:
if(checkScriptFileName(p) != 0)
fprintf(stderr, "Error: Invalid script file name: '%s'.\n", p);
根据我的理解,fprintf()应该位于msvcr120d.dll中,但它以某种方式访问msvcrt.dll并通过R.dll
有人面临过类似的问题吗?你能建议一下,在这种情况下我能做些什么来解决这个问题?(对于那些不了解这个问题的人来说)问题是如何修复这个崩溃(这通常不应该发生,因为我已经将所有正确的参数传递给了fprintf())
更新:更有趣的细节-尝试切换到CRT的静态变体,得到以下有趣的东西:
1> Generating Code...
1>LIBCMTD.lib(sprintf.obj) : error LNK2005: sprintf already defined in R.lib(R.dll)
1>LIBCMTD.lib(printf.obj) : error LNK2005: printf already defined in R.lib(R.dll)
我想出了下面的解决办法。以下是我从R.dll手动生成导入库的脚本:
:: Read more at the http://stackoverflow.com/questions/9946322/how-to-generate-an-import-library-lib-file-from-a-dll
setlocal
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
SET MACHINE=x64
SET LIBNAME=R
dumpbin /exports %LIBNAME%.dll > %LIBNAME%.exports
echo LIBRARY R > %LIBNAME%.def
echo EXPORTS >> %LIBNAME%.def
for /f "skip=19 tokens=4" %%A in (%LIBNAME%.exports) do echo %%A >> %LIBNAME%.def
start /wait win32pad.exe %LIBNAME%.def
lib /def:%LIBNAME%.def /out:%LIBNAME%.lib /machine:%MACHINE%
endlocal
实际上,我已经添加了这个
start /wait win32pad.exe %LIBNAME%.def
在运行lib.exe之前。这将启动文本编辑器,允许我手动编辑DEF文件,并从中删除所有版本的“printf”(有多个版本),它们实际上应该来自本机工具集的CRT版本
在与调整后的导入库链接后,问题就消失了
我希望这将是有用的信息的人谁的目标是嵌入到他们的Windows应用程序的R 您知道R Core的官方立场是,任何与MSVC有关的内容都是不受支持的。R是用MinGW工具链构建的,这无关紧要。这的确是一个糟糕的设计。即使使用MinGW,任何DLL都不应该导出在C运行时库中找到的符号。不幸的是,当涉及后期调试时,所有MinGW可执行文件都变得无用。在这里阅读更多。我也尝试过提到那里的工具cv2pdb,它对我没有帮助-只是没有用标准的GCC生成的调试信息从EXE生成正确的PDB。将错误报告发布到R Bugzilla,希望他们能在以后的版本中修复。事实上,只需要手动定义文件并排除DLL中由于某种原因可能发生的所有CRT内容(或者更好,完全排除CRT内容)。因此,当MINGW能够为可执行文件/DLL生成具有完整特性的PDB文件(无论是仅此文件还是标准Formart(如DWARF)之外的文件)时,我将选择MINGW。