22

我已经阅读了双方关于是否应该在 Visual Studio 项目中静态或动态链接到 C 运行时库的争论,但我仍然不完全确定该怎么想。

我的项目引入了一些第三方库(Python、HDF5、Trilinos 和 Microsoft MPI),每个库都必须使用与我的最终可执行文件相同的运行时库构建(否则它们无法链接在一起)。静态链接时,这些库中的每一个都将包含 C 运行时的副本。我读到这可能会导致问题,因为最终的可执行文件将包含运行时的多个副本,它们都不能相互交互。但是如果相同的符号被多次定义,链接器不会抱怨吗?

我想避免“DLL Hell”,但我担心在运行时的多个副本中静态链接可能产生的潜在错误。我读错了吗?

此外,我使用的是 Visual Studio 2005,并且我读到 Service Pack 1 运行时不向后兼容。这是否意味着没有 SP1 构建的应用程序将无法在具有 SP1 dll 的机器上运行,即使它们具有相同的名称(例如 msvcr80.dll)?

4

4 回答 4

27

静态链接会使您的所有 EXE 和 DLL 膨胀,并可能导致崩溃(例如,如果一个 DLL 中的代码调用 free() 并使用另一个 DLL 中的 malloc() 分配的指针)。

通过动态链接和将运行时 DLL 部署为私有程序集,您可以两全其美。这只是意味着将包含运行时 DLL 及其清单的特殊命名目录的副本放在可执行文件旁边。

有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx上的“将 Visual C++ 库 DLL 部署为私有程序集”部分,但基本上您的应用程序如下所示:

c:\Program Files\My App\MyApp.exe
c:\Program Files\My App\MyLibrary.dll
c:\Program Files\My App\Microsoft.VC80.CRT\Microsoft.VC80.CRT.manifest
c:\Program Files\My App\Microsoft.VC80.CRT\msvcr80.dll

至于你的最后一个问题,是的,目标机器需要正确版本的运行时 DLL 才能工作,但是通过将它们部署为私有程序集,你可以保证这一点。

另一个好处是非管理员用户可以安装您的应用程序(不是安装到程序文件中,而是安装在其他地方)——他们不需要将文件写入 WinSxS 区域的权限。

于 2009-04-24T21:54:30.417 回答
13

只有当您将库静态链接到 DLL 时,才会获得运行时的多个副本——每个 DLL 都会获得一个副本,exe 也将获得一个副本。如果它们都是静态库而不是 DLL,它们将全部链接在一起,并且您的所有库将共享相同的运行时。

这是链接器的工作。

于 2009-04-24T22:21:50.507 回答
1

静态库不需要静态链接到其他静态库。您只需要链接主项目中的所有静态库。这样编译器就不会抱怨多个符号。

于 2009-04-24T19:32:21.540 回答
1

...静态执行...尝试修复DLL Hell并没有那么好...只需使用静态链接在您的安装中添加额外的200k。

于 2009-04-24T19:34:24.980 回答