我正在使用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)
答案 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应用程序中的人来说是有用的信息。