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

时间:2014-07-11 18:07:22

标签: c# c++-cli interop

从非托管代码调用托管代码库时出现此错误:
运行时检查失败#2 - 围绕变量' BridgeObj'已经腐败了。

我创建的代码是:

管理lib:

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

Wrapper C ++ / CLI:

#include "stdafx.h"
#include <msclr\auto_gcroot.h>
#using "..\link\ManagedLib.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, "..\\link\\Wrapper.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;
}

1 个答案:

答案 0 :(得分:3)

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

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

接下来发生的事情是不可避免的。真实的类对象更大比编译器重新编译的类时编译器的想法更大。因此它不会在堆栈上保留足够的空间来存储对象。不可避免的,这将导致堆栈上的另一个变量被重击,只要真正的类分配_private成员就会被覆盖。

购买微软一支雪茄用于构建此诊断,这样的堆栈损坏通常非常难以诊断。并使用.h文件声明Bridge。