MSVC-可执行文件可正确构建,但DLL无法构建,缺少符号和相互依赖的对象-SSCCE / Repro

时间:2018-10-07 01:48:36

标签: c++ c visual-c++ linker msvcrt

我这里有一个可运行的可执行文件,我试图用相同的代码构建DLL,但是我遇到了一些奇怪的错误,并且在尝试了很多错误后设法查明了罪魁祸首,我决定要求帮助,因为我现在真的很困。我在我的代码中同时静态链接了SDL2和Cimgui(亲爱的Imgui C包装器),可执行文件运行良好:

#include "imgui/imgui.h"
#include "cimgui.h"
#pragma comment(lib, "cimgui.lib")

#include "SDL.h"
#undef main
#pragma comment(lib, "SDL2-staticd.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "version.lib")

void main()
{
    SDL_Init(0);
    igCreateContext(0);
    printf("OK");
}

所以现在我将项目切换到 DLL (我禁用了/IMPLIB选项,以确保链接命令中的唯一区别是{{1 }}和扩展名)。当我尝试构建时,出现关于/DLL的错误,例如:

cimgui.lib

很明显,Visual C运行时不再链接了,我真的不明白为什么,我可以立即添加它,但让我们退后一步,从代码中删除Cimgui:

cimgui.lib(imgui_draw.obj) : error LNK2001: unresolved external symbol memcmp
cimgui.lib(imgui_widgets.obj) : error LNK2001: unresolved external symbol memcpy
cimgui.lib(imgui.obj) : error LNK2001: unresolved external symbol memset

我得到13个与此类似的错误:

#include "SDL.h"
#undef main
#pragma comment(lib, "SDL2-staticd.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "version.lib")

extern "C" __declspec(dllexport) void main()
{
    SDL_Init(0);
}

因此,我手动添加了包含缺少符号的库:MSVCRTD.lib(_init_.obj) : error LNK2019: unresolved external symbol _CrtDbgReport referenced in function _CRT_RTC_INIT ucrtd.lib,然后DLL构建良好。

现在,我尝试再次添加Cimgui,但是由于以下错误而无法构建:

vcruntimed.lib

MSVCRTD.lib(utility.obj) : error LNK2019: unresolved external symbol __vcrt_initialize referenced in function __scrt_initialize_crt MSVCRTD.lib(utility.obj) : error LNK2019: unresolved external symbol __acrt_initialize referenced in function __scrt_initialize_crt 的定义在__vcrt中,但是libvcruntimed.lib的定义在__acrt中,这与libucrtd.lib冲突,即使我删除了{{ 1}}并尝试仅链接ucrtd.lib,我收到类似以下错误:

ucrtd.lib

我不知道该怎么解释,因为我没有链接libucrtd.lib

我真的不明白为什么构建DLL并不像构建可执行文件,特别是因为EXE二进制文件与DLL非常相似,我什至可以使用它作为DLL互操作,但是感觉不对。 。我敢肯定有一种方法可以构建它,而我只是不知道该怎么做。

为了完整性(以防万一),以下是EXE和DLL的链接器命令:

ucrtd.lib(ucrtbased.dll) : error LNK2005: malloc already defined in libucrtd.lib(malloc.obj)

编辑:

我制作了一个“最小,完整和可验证的示例”(自包含-包括依赖项,相对路径,VS2017项目,如果您具有Windows SDK,则应直接编译)并在此处在线发布:

https://bitbucket.org/AlanGameDev/buildmvce_so/downloads/

(您可以根据需要下载,提取或克隆)

1 个答案:

答案 0 :(得分:0)

如果将链接器标志/ VERBOSE都设置为exe / dll构建并比较结果,则将了解发生了什么。

在exe版本中,您会看到

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="">
  <table id="dyn">
    <tr>
      <td><input type="text" name="name[]" placeholder="Enter your Name" class="form-control name_list" /></td>
      <td><button type="button" name="add" id="add" class="btn btn-success">Add More</button></td>
    </tr>
  </table>
  <button type="button" id="submit"></button>

没有一个出现在dll版本中。在dll版本中,您只会看到-

1>      Found mainCRTStartup
1>        Loaded MSVCRTD.lib(exe_main.obj)
...

1>      Found __xi_a
1>        Referenced in MSVCRTD.lib(exe_main.obj)
1>        Loaded MSVCRTD.lib(initializers.obj)
1>Processed /DEFAULTLIB:kernel32.lib
1> Processed /DISALLOWLIB:msvcrt.lib
1> Processed /DISALLOWLIB:libcmt.lib
1> Processed /DISALLOWLIB:libcmtd.lib
1> Processed /DISALLOWLIB:vcruntime.lib
1>Processed /DEFAULTLIB:vcruntimed.lib
1> Processed /DISALLOWLIB:libvcruntime.lib
1> Processed /DISALLOWLIB:libvcruntimed.lib
1> Processed /DISALLOWLIB:ucrt.lib
1>Processed /DEFAULTLIB:ucrtd.lib
1> Processed /DISALLOWLIB:libucrt.lib
1> Processed /DISALLOWLIB:libucrtd.lib

这很奇怪。似乎SDL2包含了它自己的入口点_DllMainCRTStartup的实现,并且由于链接器从那里而不是crt lib那里获取它-错过了很多有用的/ DEFAULTLIB编译指示。

谷歌搜索似乎_dllMainCRTStartup包含在SDL to satisfy some Watcom needs中,并且已经怀疑它会在MSVC中引起麻烦。

如果您从源代码构建SDL,则可能应该注释掉_dllMainCRTStartup实现并(希望)成功构建。