在 Windows 7 中从托管代码调用非托管代码时出现内存泄漏
-
19-09-2019 - |
题
当我从 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 上运行的本机内存分析工具,我很高兴知道(目前我刚刚打印以控制台所有显式内存分配,并且没有差异)。
解决方案
我敢肯定,问题与编组C#的数据类型,它们的C ++计数器部分。既然你是编组返回值布尔的签署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);
的评注的解释:
在一般情况下,零或空指针 值被转换为假,任何其他 值被转换为真实的。
...结果
在1998年C ++标准库定义 载体的专业化 模板布尔。的说明 该类指示 实现应该收拾 元素使每一位BOOL仅使用 的存储器中的一个位。
所以,几乎无论您使用的价值,你会得到一个值为C ++的布尔真或假。
其他提示
不幸的是,一旦涉及的串,没有编组是简单的。
我们需要更多的数据以帮助追踪这一问题。你可以提供以下
- 地方签名
- 是怎样的记忆字符串的管理,在本机代码吗?
- 也许C++的样本里你使用API?
编辑
试试下面签名。这告诉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);
我发现使用 CLR 分析器 当发现我的内存泄漏时很有帮助。
您肯定有内存泄漏?
你是什么,用于确定内存泄漏基础。你说,你可以从性能计数器看到它,但你是什么实际观察到?你看到的是一个高层次平息一个coninously上升的曲线,或者一个?高存储器消耗经常被混淆了内存泄漏。
顺便说一句。你可以发布你的C ++函数定义呢?