8

当我从我的 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# 调用有区别。
我也不知道为什么这只发生在 Windows 7 上(两个 Windows 安装都有 .net 3.5 SP1)。

有谁知道这是什么原因?

此外,如果有人知道适用于 Window 7 的本机内存分析工具,我会很高兴知道(现在我刚刚打印以控制台所有显式内存分配并且没有区别)。

4

4 回答 4

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

评论者的解释:

对于 C++ 布尔类型:

通常,零或空指针值被转换为假,任何其他值都被转换为真。

...

1998 年的 C++ 标准库为 bool 定义了一个特殊的向量模板。类的描述表明实现应该打包元素,以便每个 bool 只使用一位内存。

因此,几乎无论您使用什么值,您都会得到一个值为 true 或 false 的 c++ 布尔值。

于 2009-10-05T15:00:46.703 回答
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);
于 2009-10-01T18:08:25.553 回答
1

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

于 2009-10-05T07:07:29.200 回答
0

你确定有内存泄漏吗?

您确定内存泄漏的依据是什么。您说您可以从性能计数器中看到它,但您实际观察到的是什么?您看到的是一条持续上升的曲线,还是一条稳定在高位的曲线?高内存消耗经常被混淆为内存泄漏。

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

于 2009-10-05T09:53:27.337 回答