A couple of weeks ago a reader of this blog approached me via Email (you can always Email me and I’ll do my best to help you if I have the time and if I can 😉 ) with a problem regarding the exception “Attempted to read or write protected memory. This is often an indication that other memory is corrupt” (which is of type System.AccessViolationException).

I immediately asked if there was some P/Invoke (Platform Invoke) code.

“Why?”, do you ask. Because in 90% of the cases, this exception occurs when a call to a P/Invoke function (either calling a Win32 API or some custom native code of your own) returns. It might even be that this piece of code you are calling is purely managed, but in its implementation it uses P/Invoke and you are not aware of it.

The main problem with P/Invoke is that .NET is very sensitive to memory corruption. If you step over some internal GC structure or some of the .NET meta data for a class things get really bad.

The causes for this error can stem from different reasons:

  • You passed a wrongly referenced pointer.
  • Inside the function there is a bug in the form of “Off-By-One” or some other memory smear or misuse.

There are two main scenarios in P/Invoke code. The first is when you correctly use the various marshaling and P/Invoke type matching simply pass a managed object (such as a string) to the function and the P/Invoke layer takes care of all the rest. In this case, you might get the exception mentioned above if:
The second is when you use IntPtr because you need to pass a pointer to a pointer or you need to receive some kind of a strange memory structure. In this case, make sure that if you pass an IntPtr buffer that you have allocated using something like Marshal.AllocHGlobal or Marshal.AllocCoTaskMem you allocated enough memory.

  • You didn’t define the marshaling attributes correctly (i.e., you should have used native pointer – IntPtr – and you didn’t)
  • You did define everything correctly, but inside the native function there is a memory related bug

If you do start to get this exception try to do the following things:

  • If you are using Marshalling attributes (MarshalAs and friends) make sure they are correct. Make sure the markings for in, out and ref are correct as well. This is a very important step. Take the time to check each and every function argument. It can save you a lot of debugging time.
  • Make sure that you are passing the right type of objects. This is specifically important if you are using IntPtrs. Make sure that you pass the right type of pointer to the function.
  • If you are calling a Windows function, there is a chance (though its usually very slim) that they do have some kind of an allocation bug, but before running to Microsoft Support, make sure you are passing the right type of pointers. If you are still in doubt, write a native sample code that calls this function and run it lots of time with additional checks to see that the integrity of the memory passed is OK.
  • If you are calling your own function, do the same as I have suggested in the point above, but in most cases, it usually a problem within the native function (if the passed pointer types are correct and the marshaling attributes are correct as well).

Remember, P/Invoke is one of .NET’s greatest features. It’s VERY fast (performance wise) and very easy to use, but its also very easy to make mistakes that can crash your whole .NET application. Use it wisely!

  • Ben Carey

    Thanks for this post. It’s nice to get an understanding for the root of the problem rather than an application-specific fix.

  • Thanks ben. I always believe that understanding the root cause is the only way to go, though, not always it is possible.

    Luckily, whenever we are dealing with managed code only, we have Reflector 😉 but in such times when we cross the boundry we need to keep in mind that .NET is much more susceptible to all the other native memory problems (memory smearing, off-by-1 and so on).

  • Anonymous

    The prototyped function needs to return a pointer to a struct. I set-up the struct as a class using “StructLayout(LayoutKind.Sequential)” and the rest of the def’s, declare an instance of the class and use that for the return value for the function call when I use it in a sub. As soon as I step into the function I get the exception. Is there another way to do this?
    -Al

  • Hello there Al, there is a reasonable chance that the function actually returns a pointer to that struct.

    Therefore, you might need to change the return type to IntPtr, get the result there and use the Marshal.PtrToStructure to convert the IntPtr to the correct structure you have defined.

    Another problem could be the calling convention.

    If this is a C DLL with C type functions you might need to set the CallingConvension parameter on the DllImport attribute to CDecl, if this is a safe call, set the attribute to safe call and so on.

  • Amhed

    Hey, I’m using Oracle Developer Tools 10g and I get the error whenever I try to connect to the database. This only happens in some of the developer workstations, we haven’t found a way to remedy the situation. Any ideas 😀 ?

  • Where does it happen? In an application you wrote? Are you writing a stored procedure with .NET in Oracle ?

    I need a bit more information as to what and how are you writing the code that causes this problem and what are you trying to access using P/Invoke.

  • Amhed

    We use Oracle Stored Procedures from .net 2.0 (using Table Adapters), it works fine, but on some dev machines the corrupted memory problem comes up and won’t even allow us to connect to the database

  • Amhed,

    So if I understand correctly, you have a .NET 2.0 application that you deploy in your organization.

    The application itself eventaully calls an Oracle Stored Procedure that is written in .NET.

    So the only P/Invoke code eventaully running was written by Oracle to execute your stored procedure right?

    Perhaps try to remove the stored procedure all together (just for the sake of the test) and see if you can connect from the problematic envrionments.

    I know there are more than a few bugs and problems in Oracle and managed stored procedures, so perhaps it would be best to search a bit in Oracle forums as well as try to install the latest patches and fixes.

  • Amhed

    Thanks 🙂

  • Anonymous

    I’m running an app that runs wonderfully on Windows XP machines. My VB loads a given DLL, then loads the given function through

    IntPtr… = GetProcAddress,

    then sets

    delegate … = System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(…

    And then happily calls the delegate lots of times. When I execute this on Win2k, and with one specific case, BOOM, I randomly get the System.AccessViolationException. Mind you, I did lots of stress testing on WinXP. Ideas?

  • Can you post some of the code that loads the DLL and more specifically where and how you define the IntPtr that get’s the GetProcAddress (as well as the LoadLibrary call).

    You might want to try and declare the function that you map using GetProcAddress to an “extern” call, this will make .NET handle the load of the DLL and the GetProcAddress of the function.

    From there on you can call the GetDelegateForFunctionPointer.

    Another thing (which is probably a long shot) – Is your Windows 2000 machine running SP4? According to the documentation (http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getdelegateforfunctionpointer.aspx) They say it should run SP4, so it might just do the trick (but its a long shot, as I’ve said before).

  • Anonymous

    Good idea to check for SP4! Unfortunately, my test machine has it.

    The specific code looks like this:

    Declare Function GetProcAddress Lib “kernel32.dll” (ByVal hModule As IntPtr, ByVal procname As String) As IntPtr
    Declare Function LoadLibraryA Lib “kernel32.dll” (ByVal dllname As String) As System.IntPtr

    Private FMyFnProcPtr As IntPtr
    Private FMyFn As FMyFnDelegate

    If Not My.Computer.FileSystem.FileExists(FullName) Then …
    MyLib = LoadLibraryA(FullName)
    If MyLib = 0 Then ….
    FMyFnProcPtr = GetProcAddress(MyLib, “FunctionNameInsideDLL”)
    FMyFn = System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(FMyFnProcPtr, GetType(FMyFnDelegate))

    My answer is looking to be “sorry, the app is only compatible with WinXP”

  • Anonymous

    It turns out I started getting a problem on XP when my remote class would raise an event, and then I had to Invoke the main window to update status – the Invoke call would freeze everything. I got rid of the event and this solved my win 2k problem; oh well, I was getting too deep into spaghetti code anyway. Thanks for your time!

  • Glad I could help.

    (even though I eventually didn’t do anything 😉 ).

  • Pingback: P/Invoke new stuff in .NET Framework 2.0 » Advanced .NET Debugging()

  • Pingback: Elegant Code » The Black Art of P/Invoke and Marshaling in .NET()

  • dev

    Thanks Eran for this post. I am facing an issue calling a c API using PInvoke. This API gets called first time without any issues. but when the it is being called second time after a series of steps. It fails with this error
    [Attempted to read or write protected memory. This is often an indication that other memory is corrupt]. could you please help me figure out the issue?

    c method

    int funcAPI(const char * dir1, const char* dir2, const char* dir3, const char* dir4, const char* dir5, int * port1, int * port2)

    C# signature:

    [DllImport(“MyDll.dll”, SetLastError = true)]
    public static extern int NativeAPI([MarshalAs(UnmanagedType.LPWStr)] string dir1,
    [MarshalAs(UnmanagedType.LPWStr)]string dir2,
    [MarshalAs(UnmanagedType.LPWStr)]string dir3,
    [MarshalAs(UnmanagedType.LPWStr)] string dir4,
    [MarshalAs(UnmanagedType.LPWStr)] string dir5,
    out int Port4,
    out int Port6);

  • I haven’t written any .NET code for the past 4 years or so.

    However, based on this:
    http://msdn.microsoft.com/en-us/library/ms235282.aspx

    You might want to use LPCStr instead of LPWStr.