none
Attempted to read or write protected memory on Interop Call. What is wrong with .NET 2.0

    Question

  • I have searched for answers on the net and what I have found was a lot of poeple complaining about the same error message coming from .net / win32 interop:

    Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

    Before someone suggests to check unmanaged library ...read the code below :

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static unsafe extern void CopyMemory(byte* dest, byte* src, int size_t);

    public unsafe static byte[] ToBinary(mystruct p)
    {
     byte[] fData = new byte[mStructureSize];
     fixed (byte* fDataPtr = fData) CopyMemory(fDataPtr, (byte*)&p, mStructureSize);
     return fData;
    }

    public unsafe static mystruct FromBinary(byte[] pData)
    {
     if (pData.Length != mStructureSize) throw new ApplicationException("Invalid Data Segment size");
     mystruct fnewstruct = new mystruct();
     fixed (byte* fDataPtr = pData)
     {
      CopyMemory((byte*)&fnewstruct, fDataPtr, mStructureSize);
      // failsafe i have tested functionality with that does seem to work but obviously copies no data.
      // CopyMemory((byte*)&fnewstruct, (byte*)&fnewstruct, mStructureSize);
     }
     return fnewstruct; // <<< error here
    }

    mStructureSize is defined as :
    System.Runtime.InteropServices.Marshal.SizeOf(typeof(mystruct))
    The same exact code worked perfectly fine in .net 1.1

    The entire situation leads me to conclude there is a bug with ether fixed component or how .NET interop handles pointers.
    As soon as something is "fixed" and then copied the error occurs

    Also, I need to understand how to make this functionality work work around for this specific case is simply not a good answer.

     


     

    Monday, April 03, 2006 4:00 PM

All replies

  •  arthurmnev wrote:

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static unsafe extern void CopyMemory(byte* dest, byte* src, int size_t);

    Kernel32.dll doesn't export any function called CopyMemory. So this shouldn't even work unless you specify EntryPoint="RtlMoveMemory" in the DllImport attribute.

    Can you post your definition of mystruct?

     

    Tuesday, April 04, 2006 7:01 AM
  • Yeah it does, kind of :) - goes back from the days of hmemcpy

     WINBASE.H:

       #define CopyMemory RtlCopyMemory 
       #define MoveMemory RtlMoveMemory
       #define ZeroMemory RtlZeroMemory

    and:

    WINNT.H:

       #define RtlCopyMemory(dst, src, len) memcpy(dst, src, len)

     

    All of that has nothing to do with current issue:

    mystruct doesnt have much in it - a double, another double and a byte

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack=1)]

    public struct mystruct

    {

    public byte a;

    public double b;

    public double c;

    }

     Mattias Sjögren wrote:

     arthurmnev wrote:

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    private static unsafe extern void CopyMemory(byte* dest, byte* src, int size_t);

    Kernel32.dll doesn't export any function called CopyMemory. So this shouldn't even work unless you specify EntryPoint="RtlMoveMemory" in the DllImport attribute.

    Can you post your definition of mystruct?

     

    Tuesday, April 04, 2006 9:00 PM
  • I made a new c# 2005 project, pasted in your code and used

    mystruct struc1 = new mystruct();

    struc1.a = 3;

    struc1.b = 4;

    struc1.c = 5;

    mStructureSize = Marshal.SizeOf(typeof(mystruct));

    byte[] b = ToBinary(struc1);

    mystruct struc2 = FromBinary(b);

    to test it, and it worked correctly without error. I left it looping thorough for a few mins too.

     

    I take it the safe way counts as a workaround...

    mystruct theStruct = new mystruct();

    theStruct.a = 3;

    theStruct.b = 4;

    theStruct.c = (byte)5;

    byte[] buffer = new byte[Marshal.SizeOf(typeof(mystruct))];

    GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);

    // struct to array

    Marshal.StructureToPtr(theStruct, gch.AddrOfPinnedObject(), false);

    gch.Free();

    // And back again

    theStruct = new mystruct();

    gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);

    theStruct = (mystruct)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(mystruct));

    gch.Free();

    Wednesday, April 05, 2006 12:06 AM
  •  arthurmnev wrote:

    Yeah it does, kind of :) - goes back from the days of hmemcpy

    Actually it doesn't. If you run Dumpbin.exe /exports kernel32.dll it will not list an entry point called CopyMemory. But for some reason it works anyway. Very weird, I wonder if it's some kind of app compat hack they have in place. Macros like the ones you listed only affect C++ code that compiles with the windows headers, not the binary Kernel32.dll and C# code that calls into it.

    Anyway, just like for jo0ls it's working fine for me. I can't reproduce the error you're seeing.

     

    Wednesday, April 05, 2006 7:01 AM