2013-02-05 3 views
3

I 오류가 일부 코드가 있습니다 다음과 같다lockbits가 필요합니까?

A는 잘못된 기능의 버전을 손질 "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은 충돌 할 때마다 다른 값을 가지므로 외부 함수가 Canvas 비트 맵을 수정한다고 생각합니다.

이것이 실제로 문제가되는 경우 fastBackgroundCanvas이 외부에서 수정되는 것을 방지하는 방법이 있습니까? 내가 LockBits이 그 것을 할 줄 알았는데 ...

을 그 답을하는 것만으로는 충분하지 있다면, 여기에 몇 가지 더 내가 해봤입니다 : 내가 fastBackgroundCanvas 또는 경우의 OnPaint를 종료 라인

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

추가 치수가 다른 기능에 의해 수정됩니다.

I (나는 그들이해야합니다 생각하는) 페인트와 같은 시간에 실행되는 비트 맵 fastBackgroundCanvas을 수정하는 기능을 방지하기 위해 뮤텍스를 사용하지만 나는 오히려 그들에게 캔버스와 같은 다른 방법을 차단하는 것 공개적이며 클래스에서 뮤텍스를 전달하지 않아도됩니다.

@ usr 님의 제안에 따르면이 버전이 더 이상 작동하지 않습니다 ... PTD 오류 일 수 있습니다. 이 관리되지 않는 메모리이기 때문에

고정이 LockBits에 의해 반환 된 버퍼 필요하지 않습니다 : 그것은 문제를 해결 도움이 때문에 대답에 내 의견을 이동 (너무 바보 프로그래머) 즉 연산 오류

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

제목에 '고정'이 언급 된 이유는 비트 맵을 편집하는 동안 일부 고정 메모리를 잠그기 위해 '고정'을 사용해야한다는 것입니다. – AppFzx

+1

해결책으로 [고정] (http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx)을 사용해야한다고 가정합니다. 이 경우에 선언문을 안전하지 않게 이동해야합니다 ... – rene

+0

@rene은'byte * canvasDataScan0'과'byte * fbgDataScan0'을 충분하게 만들거나 실제 비트 맵을 고정시키지 않기 때문에 다른 숨겨진 오류를 일으킬 수 있습니까? – AppFzx

답변

1

. 포인터 연산이 잘못되었습니다. 버그를 찾으십시오. 버그를 찾는 데 도움이되는 간단한 repro를 만드십시오.