2012-08-03 47 views
0

我正在做一些图像处理在.NET(VB 2010)。我使用下面的代码(不执行任何操作):(例如图像亮度的)损坏的内存与LockBits(DirectShow摄像头)

Sub Manipulate(IMG As Bitmap) 
    ' Dim foo(100000) As Integer - will need it later... 

    Dim bd = IMG.LockBits(New Rectangle(0, 0, IMG.Width, IMG.Height), 
          Imaging.ImageLockMode.ReadWrite, 
          Imaging.PixelFormat.Format24bppRgb) 
    Dim absstride = Math.Abs(bd.Stride) 
    Dim numbytes = absstride * IMG.Height 
    Dim bytes(numbytes - 1) As Byte 
    Dim flipped = bd.Stride < 0 
    Dim ptr = If(flipped, bd.Scan0 - numbytes + absstride, bd.Scan0) 
    System.Runtime.InteropServices.Marshal.Copy(ptr, bytes, 0, numbytes) 

    ' I'm going to put sg here 

    System.Runtime.InteropServices.Marshal.Copy(bytes, 0, ptr, numbytes) 
    IMG.UnlockBits(bd) 
End Sub 

这完全适用于简单的目的,但我的算法需要一些大的变量(见“富”以上)。在声明它(取消注释行),我突然得到例外:
取决于“富”的大小...

...无论是第一Marshal.Copy()抛出
AccessViolationException:尝试读取或写保护的内存。这通常表明其他内存已损坏。

...或“字节”的声明抛出
FatalExecutionEngineError:运行时遇到致命错误。错误的地址是0x6819d142,线程0x3690。错误代码是0xc0000005。此错误可能是CLR中的错误,也可能是用户代码中不安全或不可验证的部分。此错误的常见来源包括COM-interop或PInvoke的用户编组错误,这可能会破坏堆栈。

...或根本没有例外,一切正常。

这是怎么回事?

附加信息:我使用DirectShow从网络摄像头获取图像对象。

+0

摆脱翻转,位图永远不会在Scan0之前开始。并且不要在从不再执行的回调中获得的位图上运行此代码。除非使用Bitmap(Image)构造函数对位图进行深层复制。 – 2012-08-06 16:31:11

+0

@HansPassant我在理论上知道我应该总是从Scan0复制,但当翻转为真时,这种方法不起作用。这样我从正确的内存位置复制,我用Bitmap.GetPixel()检查它。 – Dave 2012-08-07 02:21:01

+0

@HansPassant制作深层副本确实可以解决问题,谢谢:) – Dave 2012-08-07 02:35:46

回答

0

正如Hans所指出的那样,我必须对位图进行深层次的复制,并且一切都可以正常工作。否则,我正在使用已经处理的图像。尽管这是一个沉默的错误,直到我声明了一些大的变量,这些变量用完了处置的内存,那就是GC抛出一些看似随机的错误。