1

我单步执行代码并在任务管理器中查看进程使用的 GDI 和用户对象的数量。跟踪我在评论中写的代码中的对象数量。我注意到在执行以下代码后,仍然有一个未发布的用户对象和一个未发布的 GDI 对象。我忘了在哪里释放它们?

using System;
using System.Runtime.InteropServices;

namespace UnmanagedResourcesTest
{
    class Program
    {
        static void Main(string[] args)//20 user objects; 27 GDI objects
        {
            CURSORINFO ci = new CURSORINFO();
            ci.cbSize = Marshal.SizeOf(ci);
            if (GetCursorInfo(out ci))
            {
                ////21(+1) user objects; 27 GDI objects
                if (ci.flags == CURSOR_SHOWING)
                {
                    bool result;
                    IntPtr hicon = CopyIcon(ci.hCursor);//uo1/go1
                    ////22(+1) user objects; 28(+1) GDI objects
                    ICONINFO icInfo;
                    if (GetIconInfo(hicon, out icInfo))//go1
                    {
                        ////22 user objects; 29(+1) GDI objects
                        Console.WriteLine("ICONINFO gotten");
                    }
                    result = DestroyIcon(hicon);
                    ////21(-1) user objects; 28(-1) GDI objects
                    Console.WriteLine("Is hicon destroyed? - " + result);
                }
            }
            //leaves 21-20=1 not released user object and 28-27=1 not released GDI object
            Console.ReadKey();
        }

        private const Int32 CURSOR_SHOWING = 0x00000001;

        [DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
        private static extern bool GetCursorInfo(out CURSORINFO pci);

        [DllImport("user32.dll", EntryPoint = "CopyIcon")]
        private static extern IntPtr CopyIcon(IntPtr hIcon);

        [DllImport("user32.dll", EntryPoint = "GetIconInfo")]
        private static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool DestroyIcon(IntPtr hIcon);

        [StructLayout(LayoutKind.Sequential)]
        private struct ICONINFO
        {
            public bool fIcon;         // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
            public Int32 xHotspot;     // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
            public Int32 yHotspot;     // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
            public IntPtr hbmMask;     // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
            public IntPtr hbmColor;    // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public Int32 x;
            public Int32 y;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct CURSORINFO
        {
            public Int32 cbSize;        // Specifies the size, in bytes, of the structure. 
            public Int32 flags;         // Specifies the cursor state. This parameter can be one of the following values:
            public IntPtr hCursor;          // Handle to the cursor. 
            public POINT ptScreenPos;       // A POINT structure that receives the screen coordinates of the cursor. 
        }
    }
}
4

1 回答 1

3

我找到了内存泄漏的原因。应该调用下一行:

result = DeleteObject(icInfo.hbmMask);
于 2013-09-24T14:49:26.153 回答