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是将pinvokeuser32.dllEnumWindows结合使用以获得当前打开的所有窗口的方法。

当我运行我的程序时,内存立即飙升,直到我得到一个OutOfMemoryException

从我读到的,我唯一能想到的是有某种类型的内存泄漏在EnumWindows函数,但是我很难想象user32不是完全管理的。

这是怎么回事?我该如何预防/解决它?


编辑:解决了这个问题,问题是这个列表后来与一些没有正确处理的多线程结合使用。如果您注释了ReturnAllWindows行,则表示从未达到多线程,平台调用根本不是问题。

User32和内存泄漏

如果是平台调用(即从托管代码调用本机非托管方法),则很可能内存没有以某种方式完全托管。思考一下这个问题。本机的、非托管的应用程序永远不会被编写为支持从托管代码调用。因此,对象作为非托管内存存在,由一些较低级别的系统(如果开发了的话)控制,或者不受控制。所以从托管代码调用本机方法会做所谓的装箱,它创建一个托管对象来包装本机内存。

那么。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中的内存问题通常很难跟踪。也许可以考虑分析您的应用程序,以便更好地理解您的特定问题。