简短的问题.
我刚刚得到了一个我应该与之交互的 dll.Dll 使用来自 msvcr90D.dll 的 crt(注意 D),并返回 std::strings、std::lists 和 boost::shared_ptr.运算符 new/delete 不会在任何地方重载.
I just got a dll I'm supposed to interface with. Dll uses crt from msvcr90D.dll (notice D), and returns std::strings, std::lists, and boost::shared_ptr. Operator new/delete is not overloaded anywhere.
我认为 crt mixup(发布版本中的 msvcr90.dll,或者如果使用较新的 crt 重建其中一个组件等)最终必然会导致问题,并且应该重写 dll 以避免返回任何可能调用 new/删除(即任何可以在我的代码中在 dll 中分配的内存块(可能具有不同的 crt)上调用 delete 的任何内容).
I assume crt mixup (msvcr90.dll in release build, or if one of components is rebuilt with newer crt, etc) is bound to cause problems eventually, and dll should be rewritten to avoid returning anything that could possibly call new/delete (i.e. anything that could call delete in my code on a block of memory that was allocated (possibly with different crt) in dll).
我对还是不对?
要记住的主要事情是 dll 包含 代码 而不是 内存.分配的内存属于进程(1).当您在流程中实例化一个对象时,您将调用构造函数代码.在该对象的生命周期内,您将调用其他代码(方法)来处理该对象的内存.然后当对象消失时调用析构函数代码.
The main thing to keep in mind is that dlls contain code and not memory. Memory allocated belongs to the process(1). When you instantiate an object in your process, you invoke the constructor code. During that object's lifetime you will invoke other pieces of code(methods) to work on that object's memory. Then when the object is going away the destructor code is invoked.
STL 模板不是从 dll 显式导出的.代码静态链接到每个 dll.所以当在 a.dll 中创建 std::string 并传递给 b.dll 时,每个 dll 都会有两个不同的 string::copy 方法实例.a.dll 中调用的copy 调用a.dll 的copy 方法...如果我们在b.dll 中使用s 并调用copy,将调用b.dll 中的copy 方法.
STL Templates are not explicitly exported from the dll. The code is statically linked into each dll. So when std::string s is created in a.dll and passed to b.dll, each dll will have two different instances of the string::copy method. copy called in a.dll invokes a.dll's copy method... If we are working with s in b.dll and call copy, the copy method in b.dll will be invoked.
这就是为什么在西蒙的回答中他说:
This is why in Simon's answer he says:
除非你能做到,否则坏事会发生始终保证您的整套二进制文件都是用相同的工具链.
Bad things will happen unless you can always guarantee that your entire set of binaries is all built with the same toolchain.
因为如果出于某种原因,字符串 s 的副本在 a.dll 和 b.dll 之间不同,就会发生奇怪的事情.更糟糕的是,如果字符串本身在 a.dll 和 b.dll 之间不同,并且其中一个的析构函数知道清理另一个忽略的额外内存......你可能很难追踪内存泄漏.也许更糟……a.dll 可能是针对完全不同版本的 STL(即 STLPort)构建的,而 b.dll 是使用 Microsoft 的 STL 实现构建的.
because if for some reason, string s's copy differs between a.dll and b.dll, weird things will happen. Even worse if string itself is different between a.dll and b.dll, and the destructor in one knows to clean extra memory that the other ignores... you can have difficult to track down memory leaks. Maybe even worse... a.dll might have been built against a completely different version of the STL (ie STLPort) while b.dll is built using Microsoft's STL implementation.
那你该怎么办?在我们工作的地方,我们对每个 dll 的工具链和构建设置都有严格的控制.因此,当我们开发内部 dll 时,我们可以随意传输 STL 模板.我们仍然有一些问题,在极少数情况下会因为有人没有正确设置他们的项目而出现.然而,我们发现 STL 的便利值得偶尔出现的问题.
So what should you do? Where we work, we have strict control over the toolchain and build settings for each dll. So when we develop internal dll's, we freely transfer STL templates around. We still have problems that on rare occasion crop up because someone didn't correctly setup their project. However we find the convenience of the STL worth the occasional problem that crops up.
对于将 dll 暴露给 3rd 方,那完全是另一回事.除非您想严格要求来自客户端的特定构建设置,否则您将希望避免导出 STL 模板.我不建议严格强制您的客户使用特定的构建设置……他们可能有另一个 3rd 方工具,希望您使用完全相反的构建设置.
For exposing dlls to 3rd parties, that's another story entirely. Unless you want to strictly require specific build settings from clients, you'll want to avoid exporting STL templates. I don't recommend strictly enforcing your clients to have specific build settings... they may have another 3rd party tool that expects you to use completely opposite build settings.
(1) 是的,我知道静态和局部变量在 dll 加载/卸载时被实例化/删除.
(1) Yes I know static and locals are instantiated/deleted on dll load/unload.
这篇关于从 dll 返回 std::string/std::list的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!