Удаление неуправляемого объекта из Finalize создает исключение AccessViolationException - PullRequest
1 голос
/ 01 апреля 2011

Я пишу библиотеку-оболочку, используя C ++ / CLI для неуправляемого проекта C ++. Цель состоит в том, чтобы предоставить эту библиотеку приложениям на C #. Вот что у меня есть.

#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

Дополнительная информация: Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена.

Я не вижу очевидной причины, по которой выбрасывается это исключение. Я попытался избавиться от объекта явно, вызвав Dispose из моего приложения C #. Это все еще бросает то же самое исключение.

Вот тестовое приложение:

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 ]

2 голосов
/ 01 апреля 2011

Это была ошибка конфигурации проекта.Код фактически работал нормально в режиме выпуска.

В режиме отладки я связывал некоторые релизные DLL, когда я должен был статически связываться с отладочными библиотеками.Почему это вызвало повреждение памяти, я еще не исследовал, но это решило проблему.

В противном случае приведенный выше код является правильным.

1 голос
/ 01 апреля 2011

Вы должны включить больше возможностей отладки многословной кучи.Я проверил ваш код, и он не подвел меня.Мне пришлось использовать 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...