問題描述
簡短的問題.
我剛剛得到了一個我應該與之交互的 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模板網!