2012-08-01 176 views
1

我们的软件存在定期崩溃问题。我想我已经查明了它发生的地方,但我不熟悉代码。调试非常困难。崩溃:尝试读取或写入受保护的内存c#

我们不能在我们的开发环境中重现这个问题,它发生在我们的生活环境中。用户使用刷卡登录我们的系统,终端具有磁性读卡器。每天刷卡时可能会发生一次。 MSR像键盘一样被读取。

我在不同场合连续刷过几百张卡片,并且在开发时没有问题。

有尝试追赶,但它并没有赶上什么,我们在事件查看器中得到的错误是:

“试图读取或写入保护内存这通常是指示其他内存已损坏。 “

这是我敢肯定它的崩溃的功能:

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 & 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)崩溃但它可能是ta每天或每天2次。有时它不会每天都崩溃,但通常每天都有一次。

+0

你真的检查过客户端的内存吗?可能会有一些糟糕的记忆给你留下遗憾。 – YesMan85 2012-08-01 20:01:15

+0

异常的调用堆栈是什么? – 2012-08-01 20:04:59

+0

我确实检查过各种客户端上的内存,这里没有问题,唯一运行的程序是我们的。 – 2012-08-01 20:30:47

回答

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); 
    } 
} 
+1

谢谢马特,我会试试这个,它需要一天或两天才能从实况环境中获得结果。 – 2012-08-01 20:32:04

+0

@DavidMonaghan祝你好运! – SageMage 2012-08-01 20:39:42

+0

这不能解决问题。 – 2012-08-01 21:05:03

0

这是有点晚了,但我曾与C#中的ToUnicode函数这个确切的问题。我们从来没有弄清楚如何让这个功能在没有随机崩溃的情况下工作,所以我们避免它像鼠疫一样。

相关问题