在Windows 7中从托管代码调用非托管代码时发生内存泄漏
当我从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#布尔类型是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 ++ bool类型:
通常,将零或空指针值转换为false,将其他任何值转换为true。
...
1998年的C ++标准库为bool定义了矢量模板的专门化。 类的描述表明实现应该打包元素,以便每个bool只使用一位内存。
所以,无论你使用什么值,你都会得到一个值为true或false的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);
当发现我的内存泄漏时,我发现CLR Profiler的使用很有帮助。
链接地址: http://www.djcxy.com/p/57033.html上一篇: memory leak when calling unmanaged code from managed code in Windows 7
下一篇: What strategies and tools are useful for finding memory leaks in .NET?