2012-08-01 100 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函數這個確切的問題。我們從來沒有弄清楚如何讓這個功能在沒有隨機崩潰的情況下工作,所以我們避免它像鼠疫一樣。

相關問題