【问题标题】:C++/CLI wrapper memleak when calling managed lib from unmanaged从非托管调用托管库时的 C++/CLI 包装器 memleak
【发布时间】:2014-07-11 18:07:21
【问题描述】:

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

我创建的代码是:

托管库:

使用系统;

命名空间 My.Name.Space
{
    公共课示例
    {
        公共 int 请求(字符串 xml_input,输出字符串 xml_output)
        {
            xml_output = "重新调整字符串。";
            返回0;
        }
    }
}

包装 C++/CLI:

#include “stdafx.h” #include #使用“..\link\ManagedLib.dll” 使用命名空间 System::Runtime::InteropServices; // 元帅 结构 ManagedModul { 上市: msclr::auto_gcroot<:name::space::sample> SampleModul; }; 类 __declspec(dllexport) 桥 { 私人的: ManagedModul _private; 上市: 桥() { _private.SampleModul = gcnew My::Name::Space::Sample(); }; 〜桥() { } int 请求 ( const char * xmlin, char ** xmlout ) { 系统::字符串 ^ps; _private.SampleModul->Request(gcnew System::String(xmlin), ps); * xmlout = (char*) (Marshal::StringToHGlobalAnsi(ps)).ToPointer(); 返回0; } };

示例用法:

#include “stdafx.h” #include #pragma 注释(lib,“..\\link\\Wrapper.lib”) 班桥 { 上市: 桥(); 〜桥(); int 请求 ( const char * xmlin, char ** xmlout ); }; int _tmain(int argc, _TCHAR* argv[]) { 桥BridgeObj; 字符 * 缓冲区 = NULL; BridgeObj.Request("aaaaa", & buffer ); LocalFree ( 缓冲区 ); 返回0; }

【问题讨论】:

  • 您缺少“Marshal::FreeHGlobal”(请参阅​​“Marshal::StringToHGlobalAnsi”的文档)
  • LocalFree ( buffer ) 在非托管免费数据中。只有这个'Bridge BridgeObj;'导致泄漏。

标签: c# c++-cli interop


【解决方案1】:
class Bridge
{
public:
    Bridge();
    ~Bridge();
    int Request ( const char * xmlin, char ** xmlout );
};

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多