gpt4 book ai didi

c# - lockbits 是否需要固定?

转载 作者:行者123 更新时间:2023-11-30 17:55:47 27 4
gpt4 key购买 nike

我有一些代码有错误“AccessViolationException 未被用户代码处理:试图读取或写入 protected 内存...”

违规函数的精简版如下:

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] = (byte)(canvasWalk[0] * spriteWalk[3] / 255 + spriteWalk[0]);

甚至替换为:

canvasWalk[0] = 0;

迭代变量 yx 每次崩溃时都有不同的值,所以这让我相信外部函数正在修改 Canvas位图。

如果这实际上是我的问题,有没有办法防止 fastBackgroundCanvas 被外部修改?我认为 LockBits 应该这样做...

如果这还不够回答,这里还有一些我试过的:我添加了行

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

如果 fastBackground Canvas 或尺寸被其他函数修改,则退出 OnPaint。

可以使用互斥锁来防止修改位图fastBackgroundCanvas 的函数与paint (正如我认为的那样),但我宁愿以另一种方式阻止它们,因为 Canvas 是公开的,我不想要求将互斥体传递到类之外。

根据@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);
}
}

最佳答案

将我的评论移到答案中,因为它有助于解决问题:

LockBits 返回的缓冲区不需要 Fixed,因为它是非托管内存。你的指针算法是错误的。找到错误。创建一个简单的重现来帮助找到错误。

关于c# - lockbits 是否需要固定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14716194/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com