从Windows 7中的托管代码调用非托管代码时出现内存泄漏

时间:2009-10-01 18:00:14

标签: c# c++ windows-7 memory-leaks vshost.exe

当我从C#代码中调用非托管C ++代码时,我似乎有某种内存泄漏。
C ++使用ifstream.read从文件中读取数据,并将其写入Vector。

这种情况只有在升级到Windows 7后才会发生,在Vista上不会发生,但如果我使用的是在Vista上编译的本机dll版本,它不会改变任何东西!
如果我直接运行相同的C ++代码,没有托管互操作,则没有内存泄漏! 如果我运行托管进程,但在vshost进程内,则没有内存泄漏!

这是电话签名:

        [DllImport(DllPath, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.I1)]
    public static extern bool MyMethod(
        int x, 
        string  y, 
        string  z, 
        bool    v, 
        bool    w);

和本地人:

MyDll_Export bool APIENTRY MyMethod(
int x,
const wchar_t*  y, 
const wchar_t*  z,
bool v,
bool w)

当我从C ++调用它时,我称之为:

MyMethod(1, L"My String 1", L"My String 2", true, true)

当我查看托管和非托管内存的性能计数器时,我发现所有内存都来自非托管代码。
考虑到编组非常简单,我不明白为什么直接调用C ++或通过C#调用C ++之间存在差异。
我也不知道为什么这只会在Windows 7上发生(两个Windows安装都有.net 3.5 SP1)。

有没有人知道这是什么原因?

此外,如果有人知道可以在Window 7上运行的本机内存分析工具,我很高兴知道(现在我只是打印到控制台所有显式内存分配,并没有差异)。

4 个答案:

答案 0 :(得分:5)

我确信这个问题与将C#数据类型编组到他们的C ++计数器部分有关。由于您将返回值bool编组为有符号的1字节值,您可能应该对函数参数执行相同的操作吗? C#bool类型是4个字节,也许你在那里泄漏?

此外,为字符串指定非托管类型可能会有所帮助。

[DllImport(DllPath, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool MyMethod(
        int x,
        [MarshalAs(UnmanagedType.LPWStr)]
        [In] string y,
        [MarshalAs(UnmanagedType.LPWStr)]
        [In] string z,
        [MarshalAs(UnmanagedType.I1)]
        bool v,
        [MarshalAs(UnmanagedType.I1)]
        bool w);

评论员的解释:

For the C++ bool type:

  

通常,零或空指针   任何其他值都将值转换为false   value转换为true。

...

  

1998 C ++标准库定义   向量的特化   布尔的模板。的描述   班级表明了   实施应该打包   元素使每个bool只使用   一点记忆。

所以,无论你使用什么值,你都会得到一个值为true或false的c ++布尔值。

答案 1 :(得分:2)

不幸的是,一旦你涉及字符串,没有编组很简单。

我们需要更多数据才能帮助您找到此问题。你能提供以下

吗?
  • 原生方法签名
  • 如何在本机代码中管理字符串的内存?
  • 也许您使用API​​的C ++示例?

修改

尝试以下签名。这告诉CLR不要在两个方向上编组内存,而只是传递数据。

    [DllImport(DllPath, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.I1)]
    public static extern bool MyMethod(
            int x, 
            [In] string  y, 
            [In] string  z, 
            bool    v, 
            bool    w);

答案 2 :(得分:1)

我发现在查找内存泄漏时使用CLR Profiler很有帮助。

答案 3 :(得分:0)

您确定存在内存泄漏吗?

确定内存泄漏的基础是什么?你说你可以从性能指标看到它,但你实际观察到了什么?你是否看到一条连续上升的曲线,或者一条稳定在高位的曲线?高内存消耗通常会因内存泄漏而混淆。

顺便说一句。你也可以发布C ++函数定义吗?