2011-04-01 47 views
1

我正在爲一個非託管C++項目編寫一個使用C++/CLI的包裝庫。目標是將此庫展示給C#應用程序。這是迄今爲止我所擁有的。從Finalize中刪除一個非託管對象引發AccessViolationException

#pragma once 

#include "Settings.h" 
#include "Settings/SettingsPrivate.h" 

public ref class Settings 
{ 
public: 
    Settings(); 
    virtual ~Settings(); 

protected: 
    !Settings(); 

public: 
    unsigned char GetModel(int iNumber); 


private: 
    CSettings* m_pSettings; 
}; 

#include "stdafx.h" 
#include "Managed/Settings.h" 

Settings::Settings() 
{ 
    // Pointer to unmanaged object 
    m_pSettings = new CSettings(); 
} 

Settings::~Settings() 
{ 
    this->!Settings(); 
} 

Settings::!Settings() 
{ 
    if (m_pSettings) 
    { 
     delete m_pSettings; 
     m_pSettings = NULL;   
    } 
} 

unsigned char Settings::GetModel(int iNumber) 
{ 
    return m_pSettingss->GetModel(iNumber); 
} 

的代碼執行測試應用程序,我寫的罰款。函數調用成功。問題是當GC完成這個對象時,它會拋出一個異常。

型「System.AccessViolationException」未處理的異常發生在Wrapper.dll

其他信息:試圖讀取或寫入保護內存。這通常表明其他內存已損壞。

我看不出任何明顯的原因,爲什麼拋出這個異常。我試圖通過從我的C#應用​​程序中調用Dispose來顯式地處理對象。它仍會拋出相同的異常。

這裏的測試應用程序:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace WrapperTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Settings settings = new Settings(); 
      byte b = settings.GetModel(0); 

      settings.Dispose(); 

      return; 
     } 
    } 
} 

會有人指出我在做什麼錯?

+2

沒有repro,看不到問題。我認爲問題出現在SettingsPrivate,我猜可能會造成堆損壞。 – 2011-04-01 01:06:04

+0

如果您在調試器中啓用了第一次機會AV(「調試 - >異常 - > Win32異常 - >訪問衝突」;您可能想在「工具 - >選項 - >調試」中禁用「只是我的代碼」),什麼被訪問(你還需要在C#項目中啓用本地調試,因爲我假設你正在啓動它)?沒有什麼是跳出來的,因爲這段代碼錯了。 – 2011-04-01 02:52:34

+0

@Hans:昨晚你的評論讓我走上正確的軌道來解決我的問題。如果你發佈了答案,我會給你這個問題的功勞。 – Nathanael 2011-04-01 15:51:29

回答

2

這是一個項目配置錯誤。代碼實際上在發佈模式下運行良好。

在調試模式下,我在一些發佈DLL中鏈接,當我應該靜態鏈接到調試庫時。爲什麼這導致了我尚未調查的內存損壞,但它已解決了這個問題。

否則上面貼出的代碼是正確的。

+0

這讓我想起了DLLMain問題。您不能搶先體驗運行時(即在CLR get引導之前沒有運行代碼)。 – RandomNickName42 2011-04-02 01:11:45

1

您應該啓用更詳細的堆調試功能。我測試了你的代碼,對我來說並沒有失敗。我不得不使用malloc/free而不是new/delete,因爲你沒有定義CSettings,但是效果應該是相同的。

我添加了這個以確保我有足夠的堆流失來觸發失敗,如果他們是任何腐敗;

unsigned char Settings::GetModel(int iNumber) 
{ 
    for(int i=0; i < iNumber; i++) 
     free(malloc(1024)); 
    return iNumber; 
} 

對我來說你的代碼沒有失敗。你應該看看你的一些編譯設置,你是否連接到CSettings的外部庫?如果是這樣,你需要確保CRT是相同的版本,等等。你也知道你必須使用其中一個DLL運行時不是/ MT或/ MTd。

相關問題