Index . 블로그창고 . Any comments?

DotNet Error: System.AccessViolationException: Attempted to read or write protected memory

Ryan Koehnen wrote:

I commonly get the same error on the the call: IRasterWorkspace2.CreateRasterDataset(...).

It happens most often when I make repeated calls to this method.

In .Net 1.1 the error usually surfaces as "Object reference not set to an instance of an object." .Net 2.0 gives the "attempted to write to protected memory" error.

A couple of things that help but are not a sure fix are the following.

Release the COM object as soon as you are done using it. If you are in a loop and repeatedly change the value of the .Net object by reference, release the underlying COM object before doing so.

foreach(i = 0, i < n, i++)
{
  object = [return from some ArcObjects method, property, or enum]

  //do something with object...

  Marshal.ReleaseComObject(object);
  //or in .NET 2.0 call..
  Marshal.FinalReleaseComObject(object);
  object = null;
  GC.Collect();
  GC.WaitForPendingFinalizers();
}

This seems to help, but I still occasionaly get this error in the above mentioned call to IRasterWorkspace2 :( If anybody has any further clues as to how to avoid this, it could save me alot of money with the hair transplant surgeon ;)

and

I agree with KG, in that the error seems so finicky and evasive that even for me, by changing a few lines of code (putting an arbtrary loop that does nothing in) can make the error go away or reappear at another step in the code.

My rough understanding of the cause is that .NET protected memory is very strick. Any corruption of the object metadata on the stack will cause this error. As an aside, I have also experienced this error while working with the Adobe Illustrator API COM objects through .NET. The two things that both of these experiences have in common is that in both cases the underlying objects being utilized are COM. COM treats garbage collection differently than .NET. COM will release memory once an object's reference count is zero. It is a deterministic memory handler. .NET on the other hand, uses a passive garbage collector. It will release memory to null objects only when it necessary because memory is running low. Hence the need in .NET to set COM objects to null and decriment their reference count to zero with the Marshal.FinalReleaseCOMObject() call for the underlying COM object to release it's memory in sync with the .NET runtime callable wrapper.

To keep the .NET memory on the stack in sync further with COM, after decrimenting COM objects and setting them to null, you manually call the .NET garabage collector (GC.Collect()). After that call use the GC.WaitForPendingFinalizers() call to tell .NET to wait until the garbage collector has finalized all objects targeted for collection before repopulating memory addresses.

Without doing all of these things, my basic guess is that occasionally, COM or the .NET RCW to COM is still hanging on to memory addrresses for which .NET believes are now empty and has now attempted to repopulate with new objects.

As I mentioned before, I have had some success removing this error by being dilligent about decrimenting the COM object, setting it to null, calling the garbage collector and waiting for finalization before allowing the program to move to the next operation. I'm not sure if this "four step method" is a silver bullet but applying correctly does seem to help.

On another note, I discovered the hair transplant surgery ends up being a catch 22 since I needed to solve this bug in order to afford his services in the first place. Being bald is cheaper on the wallet :)

tag: ,
블로그창고 . 댓글문법

All the works in this site except software and copyrighted materials by others (e.g., 문학) are licensed under a Creative Commons License. 소프트웨어 및 문학과 같이 다른 이에게 저작권이 있는 작품을 제외하고 모두 크리에이티브 커먼즈 라이센스를 따른다.
Thu Mar 28 17:03:36 2024 . XHTML . CSS (lightbox.css is not part of Uniqki. ;-) . Powered by Uniqki!
refresh . edit . loginout . index