1

ソフトウェアに定期的なクラッシュの問題があります。私はそれがどこで起こっているかを追跡したと思いますが、コードに慣れていません。デバッグするのは非常に困難です。

この問題を開発環境で再現することはできません。ライブ環境で発生します。ユーザーはスワイプ カードでシステムにログインし、端末には磁気スワイプ リーダーがあります。彼らがカードをスワイプするとき、おそらく1日に1回発生します。MSR はキーボードのように読み取られます。

さまざまな機会にカードを数百回連続してスワイプしましたが、開発に問題はありませんでした。

try catch がありますが、何もキャッチしません。イベント ビューアーで表示されるエラーは次のとおりです。

「保護されたメモリの読み取りまたは書き込みを試みました。これは多くの場合、他のメモリが破損していることを示しています。」

これは、クラッシュしていると確信している関数です。

    private void GetRawInputInfo(
        IntPtr rawInputHeader,
        ref IntPtr deviceHandle,
        ref bool handled,
        ref StringBuilder buffer)
    {
        try
        {
            uint cbSize = 0;
            IntPtr hRawInput;

            hRawInput = rawInputHeader;


            if (UnsafeNativeMethods.GetRawInputData(
                hRawInput,
                Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                IntPtr.Zero,
                ref cbSize,
                (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == 0)
            {
                IntPtr ptr = Marshal.AllocHGlobal((int)cbSize);

                if (ptr != IntPtr.Zero &&
                    UnsafeNativeMethods.GetRawInputData(
                        hRawInput,
                        Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                        ptr,
                        ref cbSize,
                        (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == cbSize)
                {

                    Structures.RAWINPUT raw = (Structures.RAWINPUT)Marshal.PtrToStructure(ptr, typeof(Structures.RAWINPUT));

                    deviceHandle = raw.header.hDevice;
                    handled = raw.header.dwType == Structures.RAWINPUTDEVICEDWTYPE.RIM_TYPEKEYBOARD &&
                        raw.keyboard.Message == Messages.WM_KEYDOWN;

                    if (handled)
                    {
                        byte[] state = new byte[256];

                        // Force the keyboard status cache to update
                        UnsafeNativeMethods.GetKeyState(0);

                        // Note: GetKeyboardState only returns valid state when
                        // the application has focus -- this is why we weren't
                        // getting shift keys when the application was not focused
                        if (UnsafeNativeMethods.GetKeyboardState(state))
                        {
                            //StringBuilder unmanagedBuffer = new StringBuilder(64);

                            if (UnsafeNativeMethods.ToUnicode(
                                raw.keyboard.VKey,
                                raw.keyboard.MakeCode,
                                state,
                                buffer,
                                64,
                                0) <= 0)
                            {
                                buffer.Remove(0, buffer.Length);
                            }
                        }
                    }
                }
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
        }
        catch (Exception e)
        {
            BLog.LogError("Error running: GetRawInputInfo()" + e.Message);
        }
    }

正しい方向へのヘルプまたはポインター (しゃれを意図したもの) をいただければ幸いです。

ありがとう

- - 更新しました:

これが何らかの形で役立つ場合のコールスタックは次のとおりです。

保護されたメモリを読み書きしようとしました。これは多くの場合、他のメモリが破損していることを示しています。

System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW (MSG& メッセージ) で

System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop (Int32 dwComponentID、Int32 理由、Int32 pvLoopData) で

System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner (Int32 理由、ApplicationContext コンテキスト) で

System.Windows.Forms.Application.ThreadContext.RunMessageLoop (Int32 理由、ApplicationContext コンテキスト) で

System.Windows.Forms.Application.RunDialog (フォーム フォーム) で

System.Windows.Forms.Form.ShowDialog (IWin32Window 所有者) で

System.Windows.Forms.Form.ShowDialog() で

MyApplication.UI.BaseDisplay.ShowDialog (SecurityData セキュリティ、Int32 listViewState、Nullable`1 ticketId、Int32 currentSeatPosition) で

私はマットに従って変更を加え、クラッシュに変化があるかどうかを確認しますが、1 日か 2 日かかる場合があります。毎日クラッシュするわけではありませんが、通常は毎日クラッシュします。

4

2 に答える 2

2

アプリケーションが Marshal.AllocHGlobal((int)cbSize) と Marshal.FreeHGlobal(ptr) の間のどこかで例外をスローすると、メモリの問題が発生し、最終的にアプリケーションがクラッシュする可能性があります。

この状況を改善するには、最初の if ステートメントの上で IntPtr ptr を宣言し、catch ブロックの後に finally ブロックを使用して ptr 変数が null でないことを確認し、Marshal.FreeHGlobal(ptr) を呼び出すことをお勧めします。

これで問題が解決する場合としない場合がありますが、メモリが常に割り当て解除されていることを確認することをお勧めします。

コードは次のようになります

private void GetRawInputInfo(
        IntPtr rawInputHeader,
        ref IntPtr deviceHandle,
        ref bool handled,
        ref StringBuilder buffer)
    {
        try
        {
            uint cbSize = 0;
            IntPtr hRawInput;
            IntPtr ptr;

            hRawInput = rawInputHeader;


            if (UnsafeNativeMethods.GetRawInputData(
                hRawInput,
                Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                IntPtr.Zero,
                ref cbSize,
                (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == 0)
            {
                ptr = Marshal.AllocHGlobal((int)cbSize);

                if (ptr != IntPtr.Zero &&
                    UnsafeNativeMethods.GetRawInputData(
                    hRawInput,
                    Structures.RAWINPUTDATAUICOMMAND.RID_INPUT,
                    ptr,
                    ref cbSize,
                    (uint)Marshal.SizeOf(typeof(Structures.RAWINPUTHEADER))) == cbSize)
            {

                Structures.RAWINPUT raw = (Structures.RAWINPUT)Marshal.PtrToStructure(ptr, typeof(Structures.RAWINPUT));

                deviceHandle = raw.header.hDevice;
                handled = raw.header.dwType == Structures.RAWINPUTDEVICEDWTYPE.RIM_TYPEKEYBOARD &&
                    raw.keyboard.Message == Messages.WM_KEYDOWN;

                if (handled)
                {
                    byte[] state = new byte[256];

                    // Force the keyboard status cache to update
                    UnsafeNativeMethods.GetKeyState(0);

                    // Note: GetKeyboardState only returns valid state when
                    // the application has focus -- this is why we weren't
                    // getting shift keys when the application was not focused
                    if (UnsafeNativeMethods.GetKeyboardState(state))
                    {
                        //StringBuilder unmanagedBuffer = new StringBuilder(64);

                        if (UnsafeNativeMethods.ToUnicode(
                            raw.keyboard.VKey,
                            raw.keyboard.MakeCode,
                            state,
                            buffer,
                            64,
                            0) <= 0)
                        {
                            buffer.Remove(0, buffer.Length);
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        BLog.LogError("Error running: GetRawInputInfo()" + e.Message);
    }
    finally
    {
        if (ptr != IntPtr.Zero)
            Marshal.FreeHGlobal(ptr);
    }
}
于 2012-08-01T20:23:41.870 に答える
0

これは少し遅れていますが、C#のToUnicode関数でこの正確な問題が発生しました。ランダムにクラッシュせずに関数を機能させる方法を理解できなかったため、疫病のように回避します。

于 2013-01-21T19:51:21.593 に答える