外壳扩展:C/C++运行时DLL的静态链接与动态链接
Shell Extensions: Static-Linking vs. Dynamic-Linking of C/C++ Run-Time DLLs
在构建Windows资源管理器外壳扩展(当前使用VS2010 SP1)时,您建议静态链接(到CRT、C++运行时和其他支持库(如ATL))还是动态链接 静态链接选项的好处之一是使部署更容易(事实上,通过这种方式,可以只在proc COM服务器DLL中部署shell扩展,而不需要外部依赖其他C/C++运行时DLL)。 在动态链接的情况下,如果WindowsSystem32
中的msvcr100.dll
、msvcp100.dll
等DLL由shell扩展使用,那么好处是如果Microsoft修复了这些DLL中的某些内容(例如安全修复程序),则修复程序将自动由自定义shell扩展使用
然而,糟糕的是,这些"全局"修复还可能在依赖代码中引入错误和破坏。
至于VCRedist DLL的应用程序本地部署,我不确定它在shell扩展的情况下如何工作。应该在shell扩展COM DLL中嵌入哪种清单,以引用shell扩展文件夹下的VCRedist DLL?
当多个模块相互交互时,必须使用CRT的DLL版本通常是一个相当困难的要求。一个特别重要的方面是在所有模块中使用相同的分配器。这样,在一个模块中分配的对象就可以被另一个模块的代码安全地销毁。这在C++中经常出现,做一些简单的事情,比如从函数返回std::字符串,是非常麻烦的。它是在被调用者中创建的,需要在调用者中销毁。如果函数调用是跨模块边界进行的,并且两个模块使用不同的堆,则会发生灾难。
标准C++对象的布局也与CRT实现有关。不同版本的编译器使用不同的std::string实现。如果一个模块使用与另一个模块不同的实现,那么灾难就会发生,调用方根本无法正确使用被调用方创建的对象。即使是调试设置这样简单的东西也可能导致不匹配,Microsoft CRT中的迭代器调试支持尤其因导致不匹配而臭名昭著,它使STL对象更大。
然而,这些问题在COM中是可以避免的。有一个强大的内存管理协议,基于IUnknown接口的AddRef和Release方法。这使得对象的创建者始终是对象的所有者,并负责销毁它。其他分配,如BSTR和SAFEARRAY,必须始终从保证在进程中共享的堆中进行。CoTaskMemAlloc、CoTaskMemFree和IMalloc实现了这种管道。
它有力地避免了对象布局问题,COM严格只与接口配合使用。严格禁止在互操作边界上传递C++对象或异常。唯一的实现细节是严格的__stdcall调用约定和严格绑定到接口IID的接口v-table布局。更改接口需要选择一个新的IID。
长话短说,因此您根本不需要使用CRT的共享版本。事实上,许多COM服务器都是用/MT编译的。使用/MD也很好,只有当COM服务器本身使用多个模块实现时,才考虑使用/MD。
这个问题的简短答案是"取决于"。但这可能是你已经走了多远。
然而,它真的变成了"两害相权取其轻"的选择,在很大程度上取决于你的扩展在做什么。如果是静态构建的,与非静态相比,它有多大?如果没有太大的区别,那么你显然没有使用大量的DLL代码,这也没关系。
如果你发现你的扩展从几十千字节增长到几兆字节,那么你必须考虑是让客户端下载redist包更好,还是将其作为安装的一部分。
没有一个答案总是正确的。这是一个折衷方案,你必须判断哪一个对你(和你的客户)最有意义——简单安装,还是依赖外部DLL。
如果你将redist DLL安装在与可执行文件相同的文件夹中,Windows会发现DLL本身就在那里,所以不需要任何额外的工作(不适用于shell扩展)
- 如果我想链接静态库并删除未使用的符号.txt我应该如何处理 Cmakelist
- 为什么当我在 C 程序中链接静态库时会"undefined symbol"?
- 强制链接静态库与 cmake 不起作用
- CMake 项目链接静态库
- 使用 CMake 在 Mac 上链接静态 GLFW 和 OpenGL
- DLL 链接静态库 - 未使用函数中未解析的链接器符号
- 如何使用 WAF 链接静态库?
- 无法在 Mac OS X 上链接静态资源库
- MAPI 链接静态库 (LNK2019: 未解析的外部符号)
- 为什么G 不链接静态程序
- 节点本机模块 - 链接静态库
- 在链接链接静态(GSOAP)库的共享库时,为什么会得到一个未定义的符号
- 链接静态和动态库时违反 ODR
- 代码中的MinGW::块不链接静态OpenSSL库
- Emscripten 链接静态库错误:wasm 流式编译失败:导入'env.getTempRet0'
- 如何正确链接静态类
- CMake 链接静态库和 glib 错误
- Eclipse CDT:如何在没有项目清理>>项目重建的情况下重新链接静态库
- 错误:链接静态库时出现";"
- gcc 如何链接静态库