Search code examples
c#access-violationbmp

C# - Marshal.Copy : Attempted to read or write protected memory


"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

I'm experiencing this error in the Marshal.Copy portion of my code. I do believe that my data is not corrupted nor protected.

I was wondering in what case does this occur. I have a List<> of bitmaps. This only occurs when I process the first index [0].

So here's how I did it : - First, I used this code [This code gets the pixel data of a bitmap] :

        Bitmap tmp_bitmap = BitmapFromFile[0];

        Rectangle rect = new Rectangle(0, 0, tmp_bitmap.Width, tmp_bitmap.Height);
        System.Drawing.Imaging.BitmapData bmpData =
            tmp_bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
            PixelFormat.Format24bppRgb);

        int length = bmpData.Stride * bmpData.Height;

        byte[] bytes = new byte[length];

        // Copy bitmap to byte[]
        Marshal.Copy(bmpData.Scan0, bytes, 0, length);
        tmp_bitmap.UnlockBits(bmpData);

It works fine, no errors occur.

Then, I apply this code [ This will remove the pixel data line scan padding ]:

 byte[] bytes = new byte[bmpData.Width * bmpData.Height * 3];
 for (int y = 0; y < bmpData.Height; ++y) {
 IntPtr mem = (IntPtr)((long)bmpData.Scan0 + y * bmpData.Stride * 3);
 Marshal.Copy(mem, bytes, y * bmpData.Width * 3, bmpData.Width * 3); //This is where the exception is pointed.
 }

It gives me that error whenever I'm processing the first image -- second to last, no problem at all.

I hope you can help me with this. Thank you in advance.


Solution

  • You seem to be considering 3 times the stride for every row; your code will only work for the first third of the image; after that you have indeed gone outside of your allowed range. Basically:

    bmpData.Scan0 + y * bmpData.Stride * 3
    

    looks really dodgy. The "stride" is the number of bytes (including padding) used by every line. Typically, that would be just:

    bmpData.Scan0 + y * bmpData.Stride