Search code examples
c#visual-studio-2008c++-cli

Deleting an unmanaged object from Finalize throws an AccessViolationException


I'm writing a wrapper library using C++/CLI for an unmanaged C++ project. The goal is to expose this library to C# applications. Here's what I have so far.

#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);
}

The code executes fine in the test application I wrote. The function call succeeds. The problem is that when the GC Finalizes this object, it throws an exception.

An unhandled exception of type 'System.AccessViolationException' occurred in Wrapper.dll

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

I can't see any obvious reason why this exception is being thrown. I tried disposing of the object explicitly by calling Dispose from my C# application. It still throws the same exception.

Here's the test application:

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;
        }
    }
}

Would someone point out what I'm doing wrong??


Solution

  • It was a project configuration error. The code actually ran fine in Release mode.

    In debug mode I linked in some release DLL's when I should have been statically linking against debug libraries. Why this caused memory corruption I haven't yet investigated but it has solved the problem.

    Otherwise the code posted above is correct.