奇怪的"Attempted to read or write protected memory"错误行为



我的C#WinForms程序中有一个方法,它检查图像的X列是否有黑色像素。

    static Boolean GetColumnState(Bitmap bmp, int x, int col)
    {
        BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
        Boolean state = false;
        unsafe
        {
            int* pData = (int*)pixelData.Scan0.ToPointer();
            pData += x;
            for (int i = 0; i < bmp.Height; ++i)
            {
                pData += bmp.Width;
                if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here
                { state = true; break; }
            }
        }
        bmp.UnlockBits(pixelData);
        return state;
    }

不幸的是,我得到了

"试图读取或写入受保护的内存"错误

"(Color.FromArgb(*pData)==Color.FromArgb(255,col,col))"

以下是我如何从不同的方法定义"col":

           if (GetColumnState(b1, 0, 255) == false)
            { col = 255; }
           else {col = 0;}
           // more code + loops
           GetColumnState(b1, i, col)

奇怪的是:只有当像素颜色定义为255(即黑色)时,我才会出错。。

您如何解释?请注意,我正在编写OCR程序,因此我加载了多个具有不同键值的词典。我在OCR过程中经常裁剪图像。我的幸运猜测是线程正在互相扰乱

现在,我已经找到了解决这个问题的方法,但价格是脚本执行总时间的+~150-200ms(我认为这是不必要的价格)。

通常我加载这样的字典:

        Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
        Bitmap l0 = new Bitmap(@"C:xxx.bmp", true);
            //+15 more
        lookup.Add("0", l0);
            //+15 more
        Dictionary<string, Bitmap> lookup2 = new Dictionary<string, Bitmap>();
        Bitmap nAa = new Bitmap(@"C:yyyAa.bmp", true);
            //+15 more
        lookup2.Add("A", nAa);
            //+15 more

为了解决这个问题,我必须为每个字典创建"void",并将它们加载到不同的线程中,如下所示:

void loadNumbers1()
{
        lookup4 = new Dictionary<string, Bitmap>();
        Bitmap sd = new Bitmap(@"C:xxxxxa.bmp", true);
            //+15 more
        lookup4.Add("0", s0);
            //+15 more
}
void loadNumbers2()// 4, 5, 6,
{
        //repeat
}

现在我们推出线程:

        Thread tNum2= new Thread(new ThreadStart(loadNumbers2));
        tNum2.Start();
        Thread tNum3= new Thread(new ThreadStart(loadNumbers3));
        tNum3.Start();

最后一步(如果没有此步骤程序,工作速度更快,但错误发生的频率更高):

tNum3.Join();

就是这样,现在我没有任何问题,但执行时间更长了。。关于如何在不使用多个线程的情况下以更简单的方式解决这个问题,有什么想法吗?在我的情况下,如果没有join(),我将获得5-100ms的字典加载时间,如果有join(,则最长可达300ms。无线程-最多180个(如果没有发生错误)。

抱歉发布时间过长

编辑:(永久修复)

static unsafe Boolean GetColumnState(Bitmap bmp, int x, int col)
        {
            BitmapData pixelData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
            Boolean state = false;
            unsafe
            {
                byte[] buffer = new byte[pixelData.Height * pixelData.Stride];
                Marshal.Copy(pixelData.Scan0, buffer, 0, buffer.Length);
                for (int i = 0; i < pixelData.Height - 1; ++i)
                {
                    byte red = buffer[i * pixelData.Stride + 4 * x + 2];
                    if (red == col)
                    { state = true; break; }
                }
            }
            bmp.UnlockBits(pixelData);
            return state;
        }

我不明白指针有什么错,但字节的工作原理很好@tia谢谢你指出我的问题。

有人知道为什么多线程会减慢字典加载时间而不是加快它吗

如果我正确理解代码,循环

for (int i = 0; i < bmp.Height; ++i)
{
    pData += bmp.Width;
    if (Color.FromArgb(*pData) == Color.FromArgb(255, col, col, col)) // error here
    { state = true; break; }
}

不正确。指针应该在迭代结束时递增,否则您将跳过第一行扫描并溢出读取位图缓冲区。

相关内容

最新更新