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(味精和味精)

在 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)

我已经按照 Matt 进行了更改,并会查看崩溃是否有任何变化,但可能需要一两天的时间。有时它不会每天都崩溃,但通常每天都有一个。

4

2 回答 2

2

如果应用程序在 Marshal.AllocHGlobal((int)cbSize) 和 Marshal.FreeHGlobal(ptr) 之间的某个地方抛出异常,您最终可能会遇到一些内存问题,最终导致您的应用程序预期崩溃。

为了纠正这种情况,我建议在第一个 if 语句上方声明 IntPtr ptr,然后在 catch 块之后使用 finally 块检查 ptr 变量是否不为空,然后调用 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 回答