【问题标题】:P/Invoke PostMessage crashes once the window received message一旦窗口收到消息,P/Invoke PostMessage 就会崩溃
【发布时间】:2016-10-30 00:58:55
【问题描述】:

我正在 .NET 核心上的 C# 控制台应用程序中通过 P/Invoke Win32 API 创建一个窗口。以下是核心代码。

class WindowContext
{
    public IWindow MainLoop(Action guiMethod)// this is called somewhere else
    {
        MSG msg = new MSG();
        while (msg.message != 0x12/*WM_QUIT*/)
        {
            if (PeekMessage(ref msg, IntPtr.Zero, 0, 0, 0x0001/*PM_REMOVE*/))
            {
                TranslateMessage(ref msg);
                DispatchMessage(ref msg);
            }
        }
    }

    private IntPtr WindowProc(IntPtr hWnd, uint msg, UIntPtr wParam, IntPtr lParam)
    {
        //....
    }

    public IWindow CreateWindow(Point position, Size size)// this is called to create a window
    {
        IntPtr hInstance = processHandle.DangerousGetHandle();
        string szAppName = "ImGuiApplication~";

        WNDCLASS wndclass;
        wndclass.style = 0x0002 /*CS_HREDRAW*/ | 0x0001/*CS_VREDRAW*/;
        wndclass.lpfnWndProc = WindowProc;

        // RegisterClass(ref wndclass);

        // CreateWindowEx(...)
        // ...
    }
}

但是一旦我将鼠标移到窗口上,程序就会不断崩溃。

程序“[18996] dotnet.exe”已退出,代码为 -1073740771 (0xc000041d)。

最后我发现调用 PeekMessage 时发生了崩溃。但我不知道为什么。

【问题讨论】:

    标签: c# pinvoke


    【解决方案1】:

    搜索调试了3个小时,终于找到了原因。

    WinProc 委托实例被垃圾回收。然后本机代码将访问无效的函数指针。

    我的意思是这个wndclass.lpfnWndProc = WindowProc;。 wndclass 是一个临时对象——确切地说是一个结构实例——当程序从CreateWindow 返回时,它不会存在于堆栈中。之后,由 CLR 决定是否 GC wndclass.lpfnWndProc

    所以解决方案是让wndclass 不是临时对象。例如,

    class WindowContext
    {
        WNDCLASS wndclass;
        public IWindow CreateWindow(Point position, Size size)// this is called to create a window
        {
            IntPtr hInstance = processHandle.DangerousGetHandle();
            string szAppName = "ImGuiApplication~";
    
            wndclass.style = 0x0002 /*CS_HREDRAW*/ | 0x0001/*CS_VREDRAW*/;
            wndclass.lpfnWndProc = WindowProc;
        }
    }
    

    现在 wndclass 与 WindowContext 实例的寿命相同。问题解决了。

    关于 SO 的一些类似问题:

    https://stackoverflow.com/a/5007211/3427520

    https://stackoverflow.com/a/1616718/3427520

    【讨论】:

      猜你喜欢
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2018-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多