GavH

Hi Guys,

I have a problem migrating an application to Vista. The following method which runs fine on XP, will randomly throw a memory access exception (violation) on Vista.

/// <summary>
/// Initiates a frame capture through VMR9/7 GetCurrentImage()
///
/// Returns the frame as bmp through the CaptureComplete event, along with
/// the published frame number (ie where the frame will appear in the avi) which is
/// at best an approximate
/// </summary>
[STAThread]
public void CaptureFrame()
{
if((! captureLock) && previewing)
{
captureLock = true; //we need to avoid concurrent calls, as they use the same objects

int hr = 0;
IntPtr bmpPtr = IntPtr.Zero;
IntPtr pDib = IntPtr.Zero;
Bitmap bmp = null;
BitmapInfoHeader bmi = new BitmapInfoHeader();
byte[] buffer;

try
{
//get a pointer to the image
if(! vmr7Mode) hr = videoWindow.GetCurrentImage(out pDib);
else hr = videoWindow7.GetCurrentImage(out pDib);
DsError.ThrowExceptionForHR(hr);

bmi = (BitmapInfoHeader) Marshal.PtrToStructure(pDib, typeof(BitmapInfoHeader));

if (IntPtr.Size == 32)
bmpPtr = new IntPtr(pDib.ToInt32() + bmi.Size);
else
bmpPtr = new IntPtr(pDib.ToInt64() + bmi.Size);

bmp = new Bitmap(bmi.Width, bmi.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmi.Width, bmi.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);

buffer = new byte[bmi.ImageSize];
Marshal.Copy(bmpPtr, buffer, 0, bmi.ImageSize);

Marshal.Copy(buffer, 0,bmpData.Scan0, bmi.ImageSize);

bmp.UnlockBits(bmpData);
<<EXCEPTION>> Marshal.FreeCoTaskMem(pDib); //exception here


bmp.RotateFlip(RotateFlipType.Rotate180FlipX);

//fire the event with the bmp
CaptureComplete(new Bitmap(bmp),CapturedVideoFrames,CurrentFrame);
bmp.Dispose();
}
catch
{

}
finally
{
//clean up anything we have not already dealt with
if(bmpPtr != IntPtr.Zero) Marshal.FreeCoTaskMem(bmpPtr); bmpPtr = IntPtr.Zero;
if(pDib != IntPtr.Zero) Marshal.FreeCoTaskMem(pDib); pDib = IntPtr.Zero;
GC.Collect();
captureLock = false; //re-enable capture
}
}
}

The exception is thrown by Marshal.FreeCoTaskMem() The code works a seemingly random number of times and then explodes.

Any pointers (chessey pun intended) greatfully received.

Thanks



Re: General Windows Vista Development Issues FreeCoTaskMem (Memory Access Exception) in Vista, fine in XP .NET 2

Citizen on the earth


Hi GavH,

I checked Marshal.FreeCoTaskMem method in MSDN document - http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshal.freecotaskmem(vs.80).aspx and found Windows Vista wasn't included in the support platform in .NET Framework 2.0 ( Windows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition).

The reason why only Vista is failing is most probably because vista has become more sensitive (or robust) to such kind of allocation differences.

Here is a thread discussion about "Access memory error after unmanaged interop in Vista" which is close to what you need for your reference - http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1677959&SiteID=1

Hope this helps,

Citizens on the earth





Re: General Windows Vista Development Issues FreeCoTaskMem (Memory Access Exception) in Vista, fine in XP .NET 2

Mattias Sjogren

Good thing Vista errors since it exposes bugs in your code. You're freeing the same memory more than once, that's probably the reason.

The FreeCoTaskMem(pDib) call inside the try block is unecessary since you're calling it again in the finally block. It's also buggy since it doesn't zero out the pointer afterwards.

The FreeCoTaskMem(bmpPtr) call shouldn't be there since bmpPtr doesn't point to a separately allocated buffer but to an offset inside the pDib buffer.

And finally, IntPtr.Size returns the size in bytes, so it's either 4 or 8, never 32.






Re: General Windows Vista Development Issues FreeCoTaskMem (Memory Access Exception) in Vista, fine in XP .NET 2

GavH

Thanks guys,

Both very useful, I will bare in mind with regard to Vista Compatibility.

"The FreeCoTaskMem(pDib) call inside the try block is unecessary since you're calling it again in the finally block"

Sorry that was simply a remnant of moving the dealocation around, the point was that the call to FreeCoTaskMem in the try block throws an exception, I simply moved it forward from the finally block to test that and left it in my pasted code.

"
Good thing Vista errors since it exposes bugs in your code" you are totally correct, the intptr.size is sloppy, guess I must have been thinking 32, 64 (perhaps I was drinking and coding that night!) the worst thing is that has been running seemingly well, and most certainly un detected on XP systems for a long, long while now, and I guess that within that light the tighter sensitivity and control on Vista can only be a good thing.

Thankyou all.