2011-04-01 42 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。

相关问题