2010-04-16 19 views
1
// dll 
#include <memory> 

__declspec(dllexport) std::auto_ptr<int> get(); 

__declspec(dllexport) std::auto_ptr<int> get() 
{ 
    return std::auto_ptr<int>(new int()); 
} 

// exe 
#include <iostream> 
#include <memory> 

__declspec(dllimport) std::auto_ptr<int> get(); 

int main() { 
    { 
     std::auto_ptr<int> x = get(); 
    } 
    std::cout << "done\n"; 
    getchar(); 
} 

下面的代碼運行在VC9完全確定。但是,在VC6下,我將遇到以下消息的立即崩潰。使用auto_ptr DLL引起死機

Debug Assertion Failed!

計劃: C:\項目\ use_dynamic_link \調試\ use_dynamic_link.exe 文件:dbgheap.c行:1044

表達: _CrtIsValidHeapPointer(pUserData)

它是出口的auto_ptr下VC6是不允許的?

這是一個已知的問題,即通過DLL導出STL集合類。

Access Violation When Accessing an STL Object Through A Pointer or Reference In A Different DLL or EXE

但是,我身邊谷歌並沒有看到任何提及性病:: auto_ptr的。

任何解決方法?

回答

4

DLL有自己的堆,所以你必須確保你是新的,並從同一個上下文中刪除。

+0

爲什麼在VC9中不會出現這個問題? – 2010-04-16 07:24:12

+0

好的。我確實發現爲什麼這個問題不會發生在VC9中。在VC9中,我動態鏈接到運行時庫。在VC6中,我使用靜態鏈接。看到我額外發布的答案。 – 2010-04-17 04:42:28

1

我的第一個猜測是,將VC9中的exe和dll項目設置爲將CRT作爲共享dll,而其中一個或兩個VC6項目都是針對靜態CRT(非dll)。

或者,dll和exe都是針對不同版本的共享CRT dll(因此它們實際上使用2個不同的CRT)。

在VC6中,檢查C/C++項目屬性的代碼生成類別中的運行時庫選項。確保exe和dll都以相同的DLL庫選項爲目標。

1

您違反了ODR(一個定義規則),並且很可能會將內聯函數內聯 - 因爲它們被內聯了std::auto_ptr的兩個不同定義,您將得到未定義的行爲。

最重要的是,作爲艾迪指出,當auto_ptr::~auto_ptr釋放的對象舉行,它會調用operator delete的EXE,而不是在operator new被稱爲DLL。這種不匹配也會導致崩潰。

一般來說,導出已實現的類(純粹由純虛函數組成的接口類,以及導出一個免費的工廠函數進行構建)是非常脆弱的,然後您不要在類上使用__declspec(dllexport),只能在工廠功能。

+0

看起來像一個雞蛋和雞的問題。由於異常安全,我的自然反射會在dll函數返回的指針周圍放置一個auto_ptr。但是,然後我可以遇到不同運行時問題的刪除。 – user331471 2011-07-26 14:05:05

+0

@user:嘗試'com_ptr_t',並在對象本身中實現'Release'函數。 COM/DCOM/ActiveX使用此方法可以很好地共享模塊/編譯器/語言/運行時間之間的組件。 – 2011-07-26 16:04:24

0

好的。我意識到根本原因。它是由

DLL內存管理器造成的mixup

DLL memory manager mixup

  1. 分配從DLL

  2. 返回指針內存爲EXE

  3. 嘗試刪除來自EXE的指針

步驟(3)將只正常工作,如果我們鏈接到動態運行時庫(下選擇C/C++ - >代碼生成 - >使用運行時庫)

如果我們鏈接運行時庫靜態地,DLL使用的內存管理器可能與EXE使用的內存管理器不同。

+0

你的意思是項目設置中的運行時庫選項混淆了? – 2010-04-16 08:27:51

+0

看到我編輯的帖子。 – 2010-04-17 04:41:16