C++ 静态或动态链接CRT、MFC、ATL等

C++ 静态或动态链接CRT、MFC、ATL等,c++,mfc,linker,C++,Mfc,Linker,早在90年代,当我第一次开始使用MFC时,我就习惯于动态链接我的应用程序,并提供相关的MFC DLL。这给我带来了一些问题(DLL地狱!),我转而使用静态链接——不仅仅是MFC,还有CRT和ATL。除了更大的EXE文件之外,静态链接从来没有给我带来任何问题——那么其他人遇到过什么缺点吗?是否有充分的理由再次访问动态链接?我的应用程序现在主要是STL/Boost FWIW。不,这方面没有什么新东西。保持这种状态。绝对正确 分配是在“静态”堆上完成的。由于分配-解除分配应在同一堆上完成,这意味着如果

早在90年代,当我第一次开始使用MFC时,我就习惯于动态链接我的应用程序,并提供相关的MFC DLL。这给我带来了一些问题(DLL地狱!),我转而使用静态链接——不仅仅是MFC,还有CRT和ATL。除了更大的EXE文件之外,静态链接从来没有给我带来任何问题——那么其他人遇到过什么缺点吗?是否有充分的理由再次访问动态链接?我的应用程序现在主要是STL/Boost FWIW。

不,这方面没有什么新东西。保持这种状态。

绝对正确

分配是在“静态”堆上完成的。由于分配-解除分配应在同一堆上完成,这意味着如果您提供库,则应注意客户端代码不能调用'your'
p=new LibClass()
,并使用
delete p删除该对象本身


我的结论是:要么屏蔽客户端代码的分配和解除分配,要么动态链接CRT。

只要您将使用限制在某些库中,并且不使用任何dll,您就应该是好的

不幸的是,有些库不能静态链接。我举的最好的例子是OpenMP。如果利用Visual Studio的OpenMP支持,则必须确保已安装运行时(在本例中为vcomp.dll)

如果你使用dll,那么你不能在没有一些严肃的体操来回传递一些项目。我想到了字符串。如果exe和dll是动态链接的,则在CRT中进行分配。否则,您的程序可能会尝试在一侧分配字符串,在另一侧取消分配字符串。坏事接踵而至


也就是说,我仍然静态链接我的exe和dll。在安装过程中,它减少了大量的变化,我认为值得注意的几个限制。

< P>使用DLL的一个很好的特点是,如果多个进程加载相同的DLL,它的代码可以在它们之间共享。这可以节省内存并缩短应用程序加载已被其他程序使用的dll的加载时间。

有一些缺点:

  • 更大的exe大小(特别是当您发送多个exe时)
  • 使用依赖或假定动态链接的其他DLL时出现问题(例如:无法作为静态库获取的第三方DLL)
  • 具有独立静态链接的DLL之间的不同c运行时(无跨模块分配/取消分配)
  • 没有共享组件的自动维护(没有能力让第三方模块供应商在不重新编译和更新应用程序的情况下更新其代码以解决问题)

我们为Windows应用程序进行静态链接,主要是因为它允许xcopy部署,这在安装或依赖SxS DLL时是不可能的,因为过程和机制没有很好的文档记录,也不容易远程处理。如果您在安装目录中使用本地DLL,它会起到一定的作用,但是它没有得到很好的支持。不通过远程系统上的MSI就无法轻松地进行远程安装是我们不使用动态链接的主要原因,但是(正如您所指出的)静态链接还有许多其他好处。各有利弊;希望这有助于列举它们。

我听到的大多数答案都涉及到与其他程序共享dll,或者在不需要修补软件的情况下更新这些dll

坦率地说,我认为这些是不利的,而不是有利的。当第三方dll被更新时,它的变化足以破坏您的软件。现在,硬盘空间不再像以前那么宝贵了,你的可执行文件中多了500k?谁在乎呢

  • 100%确定您的软件正在使用的dll版本是一件好事
  • 100%确信客户不会有依赖性头痛是一件好事

在我看来,好处远远大于坏处

有些软件许可证(如LGPL)要求您使用DLL或将应用程序作为用户可以链接在一起的对象文件分发。如果使用这样的库,您可能希望将其用作DLL。

内存分配不正确。当您使用DLL CRT时,应用程序中只有一个CRT,因此您可以从一个DLL中分配,并在另一个DLL中取消分配,因为它是同一个CRT,所以所有CRT都将进入同一堆。如果exe和DLL都是静态链接的,则有两个堆。对吗?至少这是我的经历。我得告诉你,能够来回传递std::string或向量会让我的生活更轻松。std::string问题的解决方案不是胡扯。静态链接或动态链接。如果您至少有一个C++ DLL,则链接到CRT DLL。可能会有更好的方法(私有程序集)被描述,可以通过页面去重复来节省系统内存。但是单个进程的虚拟地址空间实际上被减少了,而不是仅仅将库的一部分拉入可执行文件,而是将整个库映射到进程地址空间。通过映射多个DLL和ASLR,进程虚拟地址空间变得支离破碎,至少对于32位应用程序而言,这大大减少了可分配的连续内存块的大小。如果您必须使用这样的库,您可以支付赎金以实现静态链接(而不是拖拽DLL)。