User32和内存泄漏
本文关键字:泄漏 内存 User32 | 更新日期: 2023-09-27 18:14:53
经过一番阅读,我发现你用c#编写的所有代码都是托管代码,不应该产生内存泄漏。然而,我的程序的行为方式表明存在某种内存泄漏。
我的整个程序可以归结为:(目前我没有实际的代码)
while(true)
{
//Source of the "leak"
List<object> _objects = ReturnAllWindows();
//Do something awesome with the list...
System.Threading.Thread.Sleep(10);
}
ReturnAllWindows
是将pinvoke
与user32.dll
和EnumWindows
结合使用以获得当前打开的所有窗口的方法。
当我运行我的程序时,内存立即飙升,直到我得到一个OutOfMemoryException
。
从我读到的,我唯一能想到的是有某种类型的内存泄漏在EnumWindows
函数,但是我很难想象user32不是完全管理的。
这是怎么回事?我该如何预防/解决它?
编辑:解决了这个问题,问题是这个列表后来与一些没有正确处理的多线程结合使用。如果您注释了
ReturnAllWindows
行,则表示从未达到多线程,平台调用根本不是问题。
如果是平台调用(即从托管代码调用本机非托管方法),则很可能内存没有以某种方式完全托管。思考一下这个问题。本机的、非托管的应用程序永远不会被编写为支持从托管代码调用。因此,对象作为非托管内存存在,由一些较低级别的系统(如果开发了的话)控制,或者不受控制。所以从托管代码调用本机方法会做所谓的装箱,它创建一个托管对象来包装本机内存。
那么。net中存在内存泄漏吗?从技术上讲,没有。不是传统意义上的。但垃圾存在的想法绝对是正确的。处理装箱只会进一步混淆(因为没有更好的术语)GC。
我认为,在对装箱数据列表的令人敬畏的操作中,应该有一个对象的解引用。例如,如果您正在使用foreach遍历数据集合,并且在每个循环完成后不再需要该数据,则应该删除对该数据的所有托管引用。例如,考虑以下示例:
List<object> foo = new List<object>(); // Imagine this is your list of data
foreach (var item in foo)
{
// Execute an awesome expression here
}
看似无害,这些表达式永远不会释放内存,因为它总是以这样或那样的方式被引用。内存优化版本如下:
List<object> foo = new List<object>(); // Imagine this is your list of data
while (foo.Count > 0)
{
var item = foo[0];
// Execute an awesome expression here
item = null;
foo.RemoveAt(0);
}
注意,在第二个示例中没有对资源的剩余引用,并且装箱的数据现在符合收集条件。现在,这可能不是完全的问题,因为。net中的内存问题通常很难跟踪。也许可以考虑分析您的应用程序,以便更好地理解您的特定问题。