2013-02-05 101 views
3

我有有錯誤一些代碼「AccessViolationException是由用戶代碼未處理:嘗試讀取或寫入受保護的內存...」是否需要鎖定才能修復?

一個下調違規版本功能如下:

protected override void OnPaint(PaintEventArgs pe) 
{ 
    if ((updatingFastBackground) || (Calculating)) return; //ADDED FOR DEBUGGING, SEE BELOW 
      BitmapData canvasData = Canvas.LockBits(new Rectangle(Point.Empty, Canvas.Size), ImageLockMode.WriteOnly, FastPixelFormat); 
      BitmapData fbgData = fastBackground.LockBits(new Rectangle(Point.Empty, fastBackground.Size), ImageLockMode.ReadOnly, FastPixelFormat); 
      try 
      { 
       unsafe 
       { 
        byte* canvasDataScan0 = (byte*)canvasData.Scan0.ToPointer(); 
        byte* fbgDataScan0 = (byte*)fbgData.Scan0.ToPointer(); 
        Rectangle spriteBounds = new Rectangle(Point.Empty, ButtonImages.ImageSize); 
        for (int i = 0; i < ButtonImages.Images.Count; i++) 
        { 
         // Button offset location 
         Point l = new Point(
          (int)((i % columnCount) * hStep + myIVM.Location.X), 
          (int)((i/columnCount) * vStep + myIVM.Location.Y)); 
         // Paint at current location? 
         if (buttonPaintBounds.Contains(l)) 
         { 
          BitmapData spriteData = buttonBitmaps[i].LockBits(spriteBounds, ImageLockMode.ReadOnly, FastPixelFormat); 
          try 
          { 
           int spriteLeft = Math.Max(l.X, 0); 
           int spriteRight = Math.Min(l.X + ButtonImages.ImageSize.Width, canvasData.Width); 
           int spriteTop = Math.Max(l.Y, 0); 
           int spriteBottom = Math.Min(l.Y + ButtonImages.ImageSize.Height, canvasData.Height); 
           int spriteWidth = spriteRight - spriteLeft; 
           int spriteHeight = spriteBottom - spriteTop; 
           byte* canvasRowLeft = canvasDataScan0 + (spriteTop * canvasData.Stride) + spriteLeft * 4; 
           byte* spriteRowLeft = 
            (byte*)spriteData.Scan0.ToPointer() + 
            Math.Max((spriteTop - l.Y), 0) * spriteData.Stride + 
            Math.Max((spriteLeft - l.X), 0) * 4; 
           for (int y = 0; y < spriteHeight; y++) 
           { 
            canvasRowLeft += canvasData.Stride; 
            spriteRowLeft += spriteData.Stride; 
            Byte* canvasWalk = (Byte*)canvasRowLeft; 
            Byte* spriteWalk = (Byte*)spriteRowLeft; 
            for (int x = 0; x < spriteWidth; x++) 
            { 
             if (spriteWalk[3] != 255) 
             { 
              canvasWalk[0] = (byte)(canvasWalk[0] * spriteWalk[3]/255 + spriteWalk[0]); 
              canvasWalk[1] = (byte)(canvasWalk[1] * spriteWalk[3]/255 + spriteWalk[1]); 
              canvasWalk[2] = (byte)(canvasWalk[2] * spriteWalk[3]/255 + spriteWalk[2]); 
             } 
             canvasWalk += 4; 
             spriteWalk += 4; 
            } 
           } 
           thesePoints.Add(l); 
          } 
          finally 
          { 
           buttonBitmaps[i].UnlockBits(spriteData); 
          } 
         } 

canvasWalk[0] = 0; 
:當與替換

canvasWalk[0] = (byte)(canvasWalk[0] * spriteWalk[3]/255 + spriteWalk[0]); 

甚至:在線路中發生

錯誤

迭代變量yx每次崩潰時都有不同的值,所以這讓我相信一個外部函數正在修改位圖。

如果這實際上是我的問題,是否有辦法阻止fastBackgroundCanvas被外部修改?我以爲LockBits是應該做的是...

如果這還不夠回答,這裏的多一些我已經試過: 我增加了行

if ((updatingFastBackground) || (Calculating)) return; 

如果fastBackgroundCanvas或退出的OnPaint其他功能正在修改尺寸。

使用互斥來防止修改從在同一時間油漆中運行(因爲我認爲他們必須)的位圖fastBackgroundCanvas的功能,但我寧願阻止他們的另一種方式爲畫布是公開的,我不想要求在課堂上傳遞互斥鎖。

每@usr的建議,這個進一步修剪版本不會失敗......必須是PTD錯誤。 (程序員太愚蠢),即算術錯誤

protected override void OnPaint(PaintEventArgs pe) 
{ 
    if ((updatingFastBackground) || (Calculating)) return; //ADDED FOR DEBUGGING, SEE BELOW 
      BitmapData canvasData = Canvas.LockBits(new Rectangle(Point.Empty, Canvas.Size), ImageLockMode.WriteOnly, FastPixelFormat); 
      BitmapData fbgData = fastBackground.LockBits(new Rectangle(Point.Empty, fastBackground.Size), ImageLockMode.ReadOnly, FastPixelFormat); 
      try 
      { 
       unsafe 
       { 
        byte* canvasDataScan0 = (byte*)canvasData.Scan0.ToPointer(); 
        byte* fbgDataScan0 = (byte*)fbgData.Scan0.ToPointer(); 
        Rectangle spriteBounds = new Rectangle(Point.Empty, ButtonImages.ImageSize); 
        for (int i = 0; i < ButtonImages.Images.Count; i++) 
        { 
         // Button offset location 
         Point l = new Point(
          (int)((i % columnCount) * hStep + myIVM.Location.X), 
          (int)((i/columnCount) * vStep + myIVM.Location.Y)); 
         // Paint at current location? 
         if (buttonPaintBounds.Contains(l)) 
         { 
          BitmapData spriteData = buttonBitmaps[i].LockBits(spriteBounds, ImageLockMode.ReadOnly, FastPixelFormat); 
          try 
          { 
           byte* canvasRowLeft = canvasDataScan0; 
           byte* spriteRowLeft = (byte*)spriteData.Scan0.ToPointer(); 
           for (int y = 0; y < 145; y++) 
           { 
            canvasRowLeft += canvasData.Stride; 
            spriteRowLeft += spriteData.Stride; 
            Byte* canvasWalk = (Byte*)canvasRowLeft; 
            Byte* spriteWalk = (Byte*)spriteRowLeft; 
            for (int x = 0; x < 145; x++) 
            { 
             if (spriteWalk[3] != 255) 
             { 
              canvasWalk[0] = 0; 
              canvasWalk[1] = 0; 
              canvasWalk[2] = 0; 
             } 
             canvasWalk += 4; 
             spriteWalk += 4; 
            } 
           } 
           thesePoints.Add(l); 
          } 
          finally 
          { 
           buttonBitmaps[i].UnlockBits(spriteData); 
          } 
         } 
+0

標題提到'fixed'是我懷疑我應該使用'fixed'在編輯位圖來鎖定一些內存的原因。 – AppFzx

+1

我認爲它需要使用[fixed](http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx)作爲解決方案。在這種情況下,你必須將他們的聲明移到不安全的地方...... – rene

+0

@rene會使'byte * canvasDataScan0'和'byte * fbgDataScan0'足夠或者會導致其他隱藏錯誤,因爲它不會使實際位圖得到修復? – AppFzx

回答

1

移動我的評論到答案,因爲它幫助解決的問題:

固定不需要通過LockBits返回的緩衝區,因爲它是託管內存。你的指針算術是錯誤的。找到錯誤。創建一個簡單的repro來幫助查找錯誤。

相關問題