在调用标准C函数fprintf()时,使用嵌入式R.dll编译的C程序崩溃

时间:2015-10-14 22:11:28

标签: c r dll

我正在使用MSVC2013 Update 5并从Revolution R 3.2.2 x64导入R.dll库以编译使用嵌入式R.dll的Rserve(https://rforge.net/Rserve/)自定义版本。 CRT类型是多线程调试DLL。以非常奇怪的方式调用fprintf(stderr,...)时程序崩溃:

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)

1 个答案:

答案 0 :(得分:0)

我想出了followinf解决方案。这是我从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文件,并从中删除所有应该从本机工具集的CRT版本实际应用的“printf”(有多个)。

在与这样调整后的导入库链接后,问题就消失了。

我希望这对于那些希望将R嵌入到他们的Windows应用程序中的人来说是有用的信息。