2016-10-29 24 views
0

.NETコアのC#コンソールアプリケーションでP/Invoke Win32 APIを使用してウィンドウを作成しています。以下は、コアコードです。P/Invokeウィンドウがメッセージを受信するとPostMessageがクラッシュする

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が呼び出されたときにクラッシュが発生していることがわかりました。しかし、私は理由を伝えることができませんでした。

答えて

0

3時間の検索とデバッグ後、最終的に原因を見つけました。

WinProcデリゲートインスタンスがガベージコレクションされています。その後、ネイティブコードは無効な関数ポインタにアクセスします。

この意味はwndclass.lpfnWndProc = WindowProc;です。 wndclassは、一時的なオブジェクトであり、構造体のインスタンスであり、プログラムがCreateWindowから返ったときにスタックに存在しません。その後、GC wndclass.lpfnWndProcのいずれかを判断するのはCLRの責任です。

解決策は、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

関連する問題