Приложение C ++ / CLI случайно падает при сборках выпуска - PullRequest
4 голосов
/ 09 января 2011

Я создал смешанную DLL C ++ / CLI, которую я использую из приложения C # Winforms. Я тщательно проверил конфигурацию сборки, чтобы быть уверенным, что я связываюсь с отладочными библиотеками в режиме отладки и не отладочными библиотеками в версии.

На данный момент приложение ничего не делает, просто создает собственный класс в управляемой оболочке, как этот (шаблон синглтона для обеспечения единственного экземпляра класса):

static ManagedClassWrapper ^ GetInstance(){
                if(_me == nullptr){
                    _me = gcnew ManagedClassWrapper();
                    _me->_Impl = new NativeClass();
                }

                return _me;
            };

где _me и _impl

private:
    NativeClass * _Impl;
    static ManagedClassWrapper ^ _me = nullptr;

В форме нажатия кнопки я делаю только это:

private void button1_Click(object sender, EventArgs e)
{
    ManagedClassWrapper mcw = ManagedClassWrapper.GetInstance();
}

Также у меня есть стандартная нативная точка входа, как обычно DllMain. В сборке DEBUG я использую

_CrtSetReportHook( QaDMemManager::report );
_CrtSetDbgFlag((_CRTDBG_LEAK_CHECK_DF) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));

в начале DllMain, в сборке DEBUG, я также переопределил новое:

#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#define LOG_LEVEL Logger::NOTICE
#include <stdlib.h>
#include <crtdbg.h>
#pragma warning(disable:4291)
#define new new(_NORMAL_BLOCK,__FILE__, __LINE__)
#else
#define LOG_LEVEL Logger::INFO
#endif

как я обычно делаю для своих приложений, не относящихся к MFC, чтобы получить хорошую утечку памяти.

Конструктор NativeClass пуст.

В сборках Debug все работает нормально, я вижу утечки памяти в нативном коде, никаких сбоев.

Но в версии Release однажды из 10 мое приложение просто падает, когда я нажимаю эту кнопку1. Это означает: я могу запустить 10 экземпляров своего приложения, 9 будет работать нормально, независимо от того, сколько раз я нажму кнопку 1, но 10-е будет зависать каждый раз, когда я нажимаю кнопку 1 (после аварии я нажимаю Продолжить в окне исключений и т.д. Я могу нажать кнопку 1 много раз).

Исключением является следующее:

************** Exception Text **************
System.TypeInitializationException: The type initializer for '<Module>' threw an exception. ---> System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at _initterm((fnptr)* pfbegin, (fnptr)* pfend)
   at <CrtImplementationDetails>.LanguageSupport.InitializeNative(LanguageSupport* )
   at <CrtImplementationDetails>.LanguageSupport._Initialize(LanguageSupport* )
   at <CrtImplementationDetails>.LanguageSupport.Initialize(LanguageSupport* )
   at .cctor()
   --- End of inner exception stack trace ---
   at TestAudioInOut.TestForm.button1_Click(Object sender, EventArgs e)
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 4.0.0.0
    Win32 Version: 4.0.30319.1 (RTMRel.030319-0100)
    CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
----------------------------------------
TestAudioInOut
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///V:/Test/bin/Release/Test.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 4.0.0.0
    Win32 Version: 4.0.30319.1 built by: RTMRel
    CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
    Assembly Version: 4.0.0.0
    Win32 Version: 4.0.30319.1 built by: RTMRel
    CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System
    Assembly Version: 4.0.0.0
    Win32 Version: 4.0.30319.1 built by: RTMRel
    CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
Mixed.DLL
    Assembly Version: 1.0.4026.39493
    Win32 Version: 
    CodeBase: file:///V:/Test/bin/Release/Mixed.DLL
----------------------------------------

В чем может быть проблема (как я понимаю, TypeInitializationException означает, что что-то не так с построением объектов) и почему это происходит только в режиме Release?

1 Ответ

5 голосов
/ 10 января 2011

Это не имеет никакого отношения к фрагменту кода, который вы разместили, код бомб перед созданием ManagedClassWrapper.Класс <Module> является классом-оберткой для всего кода класса non-ref, который вы написали.Он взрывается, когда пытается вызвать инициализаторы вашего неуправляемого кода.Это AccessViolation, обычный способ для неуправляемого кода совершить пикирование в нос.

Чтобы отладить это, вы должны включить неуправляемую отладку в своем проекте C #.Project + Properties, вкладка Debug, отметьте галочкой «Включить отладку неуправляемого кода».Затем Отладка + Исключения, отметьте флаг Брошенный на «Исключения Win32».Запустите ваш код, пока не произойдет сбой, отладчик остановится в месте сбоя.Должен дать вам некоторое представление о том, где находится ошибка.Используйте обычные методы отладки, с которыми вы знакомы при работе с неуправляемым кодом.Удачи с этим.

...