未连接监视器时 DWM 泄漏内存 Windows 8

DWM Leaks Memory When No Monitor Connected Windows 8

简单地说,如果没有连接显示器并且您正在 windows 8 嵌入式上执行一些 "windows" 操作,dwm.exe 开始分配内存,永不停止.

为了重新生成并向您展示所有问题,我编写了一个正在执行 "Create a new Form and show it, if there is one created close it first"

的应用程序
public partial class PopupWindows : Form
{
    private Timer _t;
    private Form _form;
    public PopupWindows()
    {
        InitializeComponent();
        this.Size = new Size(500, 500);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        _t = new Timer();
        _t.Tick += (o, ea) =>
        {
            _form?.Close();
            (_form = new Form() { Size = this.Size }).Show();
        };
        _t.Interval = 1000;
        _t.Enabled = true;
    }
}

如果你运行这个应用程序并拔掉显示器,dwm开始分配页面 这是 pslist -m 当监视器连接时的输出

Name                Pid      VM      WS    Priv Priv Pk   Faults   NonP Page
dwm                 840  123528   14400   11264   13044    55125      7  212

一段时间后,但 显示器仍处于连接状态

dwm                 840  117144   15808   12732   13044    94051      7  200

正在断开监视器并且dwm.exe开始分配

dwm                 840  214660   14444   12664   13044   137409     13  400

下面是输出,您可以在其中看到分配 dwm.exe 正在执行

C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  251956   14460   12740   13044   137413     16  477
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  251956   14460   12740   13044   137413     16  477
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  251956   14460   12740   13044   137413     16  477
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  252964   14460   12740   13044   137413     16  479
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  252964   14460   12740   13044   137413     16  479
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  253972   14460   12744   13044   137413     16  481
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  253972   14460   12744   13044   137413     16  481
C:\PSTools>pslist.exe -m|findstr "dwm"
dwm                 840  254980   14460   12744   13044   137413     16  483

dwm 的这种奇怪行为永远不会停止,直到您连接显示器或对计算机进行 vnc 连接。

在没有监视器的情况下运行一段时间后,每个os组件开始抱怨内存,最后出现蓝屏死机.

最后一张给大家看

dwm                 840  807516   15624   14216   17240   147413     50 1603

这是显示我的 popupwindows.exe 运行ning

多少分钟的输出
Name                Pid Pri Thd  Hnd   Priv        CPU Time    Elapsed Time
PopupWindows       2052   6   4  138   9468     0:00:00.140     0:23:07.332

如您所见,在设备上没有监视器的情况下大约 20 分钟后,dwm.exe 使用 807516 字节 VM 和 1603 页。

像 vnc 所做的那样(定期将整个屏幕位图复制到应用程序内存)解决了 dwm 的分配问题(我认为 dwm 缓存了它的输出,但没有人来要求更改,所以它把所有的都保存在内存,永远不会清理)。

下面是开始隐藏并定期将屏幕图像复制到应用程序内存中的应用程序

public partial class HiddenForm : Form
{
    IntPtr _this;

    private System.Windows.Forms.Timer _timer;
    private Bitmap _bmp = null;
    public HiddenForm()
    {
        this.Visible = false;
        this.ShowInTaskbar = false;
        this.FormBorderStyle = FormBorderStyle.None;
        this.HandleCreated += (s, e) => _this = this.Handle;
        this.Load += (s, e) => this.Size = new Size(0, 0);
        CreateHandle();
        CreateControl();

        _timer = new System.Windows.Forms.Timer();
        _timer.Tick += _timer_Tick;
        _timer.Interval = 2000;
        _timer.Start();
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        if (Screen.PrimaryScreen == null)
            return;

        if (_bmp == null)
        {
            using (Graphics g = CreateGraphics())
            {
                _bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, g);
            }
        }
        using (Graphics grp = Graphics.FromImage(_bmp))
        {
            grp.CopyFromScreen(0, 0, 0, 0, _bmp.Size);
        }
    }
}

这是启动我的应用程序后的输出

Name                Pid      VM      WS    Priv Priv Pk   Faults   NonP Page
dwm                 832  117876   20188   19624   35004   184497      7  185

正在使用 pskill 等待一段时间终止我的应用程序

dwm                 832  182388   20264   19852   35004   421343     11  317

它开始增加以重新检查我们的应用程序我通过键入再次启动它

C:\HiddenForm.exe

和 dwm.exe 内存分配神奇地下降了。

dwm                 832  126384   27900   27364   35144   556729      7  187