Повреждение кучи смешанного нативного и управляемого кода - PullRequest
1 голос
/ 11 января 2012

Я использую Visual Studio 2010 и импортирую собственную C ++ DLL в C #.Когда я просто вызываю функции из DLL и ничего не делаю в своем коде на C #, все работает как надо, но когда я начинаю делать другие вещи в интерфейсе, я получаю ошибку:

Управляемая отладкаПомощник 'FatalExecutionEngineError' обнаружил проблему в 'D: \ Jeff \ 4YP \ ImageViewerApp \ ImageViewerApp \ bin \ Debug \ ImageViewerApp.vshost.exe'.Дополнительная информация: во время выполнения произошла фатальная ошибка.Адрес ошибки был 0x6b4f8127 в потоке 0x1460.Код ошибки 0xc0000005.Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях пользовательского кода.Распространенными источниками этой ошибки являются ошибки пользовательского маршалинга для COM-взаимодействия или PInvoke, которые могут повредить стек.

Я считаю, что это проблема повреждения кучи.Я попытался поиграться с кодом в DLL (который в основном экспортирует класс), и мне удалось запустить программу, когда я удаляю все строки, которые присваиваются (не указательным) переменным класса.Но указатели и переменные локальных функций, похоже, не приводят к повреждению.И довольно странно, что в конкретных случаях переменных класса типа int, float, double не происходит искажения, но это происходит для моих пользовательских типов и bool (я не пробовал все типы).

Что может вызвать этот довольно запутанный сценарий?

Вот код из моей C ++ DLL:

#pragma once

#include "stdafx.h"
#include "GlobalClassifier.h"

const int frameRate = 33;
const int jointFeaturesCount = 9;

namespace MyKinectDll
{
    typedef struct vector
    {
        public:
            float x;
            float y;
            float z;
    } VECTOR;

    [event_receiver(native)]
    class __declspec(dllexport) MyKinect
    {
        public:
            MyKinect(void)
            {
                //Fails when these lines are included:
                //initialise hand positions
                leftHandPos.x = 0;
                leftHandPos.y = 0;
                leftHandPos.z = 0;
                rightHandPos.x = 0;
                rightHandPos.y = 0;
                rightHandPos.z = 0;

                bGotNewGesture = false;
                latestGesture = CClassifier::GestureType::Left_Circular;

                //It doesn't fail when these lines are included:

                //Create sensor
                mySensor = new CNuiSensor();

                //Create and initialise classifier
                myClassifier = new CGlobalClassifier(mySensor, frameRate, jointFeaturesCount);
                myClassifier->Initialise("model.dat");

                //Initialise sensor
                mySensor->Nui_Init();
            };

            ~MyKinect(void)
            {
            };

        private:
            CGlobalClassifier *myClassifier;
            CNuiSensor *mySensor;
            bool bGotNewGesture;
            CClassifier::GestureType latestGesture;
            VECTOR leftHandPos;
            VECTOR rightHandPos;
        };
    };

А вот оболочка импорта C #:

struct UnmanWrap
{
    //Import constructor
    [DllImport("MyKinectDll.dll", EntryPoint = "??0MyKinect@MyKinectDll@@QAE@XZ",
               CallingConvention = CallingConvention.ThisCall)]
    public static extern void Constructor(ref UnmanWrap t);
}

public class MyKinectWrap
{
    private UnmanWrap unman;

    public MyKinectWrap()
    {
        //Add a path to location of the DLL file.
        Environment.SetEnvironmentVariable("PATH","D:\\Jeff\\4YP\\MyKinectDll2\\Release");

        this.unman = new UnmanWrap();
        UnmanWrap.Constructor(ref this.unman);
    }
}
...