从非托管调用托管库时C ++ / CLI包装memleak

从非托管代码调用托管代码库时出现此错误:
运行时检查失败#2 - 变量“BridgeObj”周围的堆栈已损坏。

我创建的代码是:

托管库:

using System;

namespace My.Name.Space
{
    public class Sample
    {
        public int Request(string xml_input, out string xml_output)
        {
            xml_output = "Retun string.";
            return 0;
        }
    }
}

包装器C ++ / CLI:

#include "stdafx.h"
#include <msclrauto_gcroot.h>
#using "..linkManagedLib.dll"
using namespace System::Runtime::InteropServices; // Marshal

struct ManagedModul
{
    public: 
        msclr::auto_gcroot<My::Name::Space::Sample^> SampleModul;
};

class __declspec(dllexport) Bridge
{
private: 
    ManagedModul _private;
public:
    Bridge()
    {
        _private.SampleModul = gcnew My::Name::Space::Sample();
    };

    ~Bridge()
    {
    }

    int Request ( const char * xmlin, char ** xmlout )
    {
        System::String ^ps; 
        _private.SampleModul->Request(gcnew System::String(xmlin), ps);
        * xmlout = (char*) (Marshal::StringToHGlobalAnsi(ps)).ToPointer();
        return 0;
    }
};

示例用法:

#include "stdafx.h"
#include <Windows.h>

#pragma comment ( lib, "..linkWrapper.lib" )

class Bridge
{
public:
    Bridge();
    ~Bridge();
    int Request ( const char * xmlin, char ** xmlout );
};

int _tmain(int argc, _TCHAR* argv[])
{
    Bridge BridgeObj;
    char * buffer = NULL;
    BridgeObj.Request("aaaaa", & buffer );
    LocalFree ( buffer );
    return 0;
}

class Bridge
{
public:
    Bridge();
    ~Bridge();
    int Request ( const char * xmlin, char ** xmlout );
};

这是一个非常非常糟糕的做法。 您没有使用两个项目中使用的.h文件,而是重新声明了Bridge类。 并且弄错了,你错过了_private成员。 这总是出错。 如果不是那么马上,那么在你修改真实的Bridge类的一年之后。

接下来发生的事情是不可避免的。 真正的类对象比编译器在编译重新声明的类时认为的要大。 所以它不会在堆栈上保留足够的空间来存储对象。 不可避免的是,这将导致堆栈中的另一个变量被打乱,只要真正的类分配_private成员就会被覆盖。

购买微软雪茄在这个诊断中构建,像这样的堆栈损坏通常非常难以诊断。 并使用.h文件来声明Bridge。

链接地址: http://www.djcxy.com/p/59615.html

上一篇: C++/CLI wrapper memleak when calling managed lib from unmanaged

下一篇: Including headers from an unmanaged C++ code inside C++/CLI code