none
Why AccessViolationException thrown in Marshal.PtrToStructure does not have stack trace ? RRS feed

  • Question

  • Hello,

    I don't understand why an AccessViolationException thrown in Marshal.PtrToStructure causes CLR to shutdown while the same exception in Marshal.ReadIntPtr doesn't. After all IntPtr is also structure as well. It makes very hard to debug/log interop bugs in complex code. See example:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.ExceptionServices;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Text;

    namespace ExceptionTest
    {
     class Program
     {
      [HandleProcessCorruptedStateExceptions]
      static void Main(string[] args)
      {
       AppDomain.CurrentDomain.UnhandledException += (sender, e) => Console.WriteLine("Unhandled: {0}", e.ExceptionObject);
       try
       {
        //Marshal.ReadIntPtr(new IntPtr(1));
        //Marshal.PtrToStructure(new IntPtr(1), typeof(Test));
       }
       catch (Exception e)
       {
        Console.WriteLine("Main: {0}", e);
       }
       Console.ReadLine();
      }

     }

     [StructLayout(LayoutKind.Sequential)]
     internal struct Test
     {
      public int X;
     }
    }

    For Marshal.ReadIntPtr the exception is caught in Main method having full stack trace and line number:

    System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
       at System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr ptr, Int32 ofs)
       at System.Runtime.InteropServices.Marshal.ReadIntPtr(IntPtr ptr)
       at ExceptionTest.Program.Main(String[] args) in ...Program.cs:line 19

    For Marshal.PtrToStructure it is handled by UnhandledException handler without stacktrace:

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

    Why is the AccessViolationException in PtrToStructure considered as more serious than in ReadIntPtr ? Is there any way to log stacktrace (not under debugger) when the exception is thrown in PtrToStructure method ?

    Thanks.

    • Edited by Petr Vones Friday, June 1, 2012 9:28 PM
    Friday, June 1, 2012 9:14 PM

Answers

  • 1. The AV exception thrown by Marshal.PtrToStructure is NOT handled by your UnhandledException handler.

    2. Marshal.ReadIntPtr() is a method that running on CLR, however, a call to Marshal.PtrToStructure() will be forwared to CLR, and executed inside CLR. In another words, your call to Marshal.PtrToStructure() interrupted the runtime, so the execution of managed code will be terminated immediately.

    3. As Karel suggested, you can capture a memory dump, and analysis the 1st chance exception's call stack to locate the root cause.


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Regards,
    Eric Yang
    Microsoft Online Community Support

    • Marked as answer by Petr Vones Monday, June 11, 2012 10:42 AM
    Monday, June 11, 2012 10:35 AM

All replies

  • Maybe Marshal.PtrToStructure corrupted the stack so much that the stack trace is not available?

    Managed stack trace in AV is 'nice to have thing'. The best approach is to collect dumps from crashes like this and investigate them.

    -Karel

    Saturday, June 2, 2012 12:11 AM
    Moderator
  • The operation performed by PtrToStructure is same as ReadIntPtr in my example. It reads four bytes from invalid pointer to address 0x00000001. I don't understand how this can corrupt stack.
    • Edited by Petr Vones Sunday, June 3, 2012 10:25 AM
    Sunday, June 3, 2012 10:22 AM
  • Hi Petr,

    Please check this:

    http://www.aspnet-answers.com/microsoft/VB-NET/31898423/thrown-exception-in-marshalptrtostructure.aspx


    Regards, http://shwetamannjain.blogspot.com or https://shwetalodha.wordpress.com/

    Monday, June 4, 2012 3:21 AM
  • Hi Petr

    Probably this is due to DEP (Data Execution Prevention).  This is a “feature” to stop viruses from being able to attack the system’s memory.  In this case, it was stopping the application from importing the reference correctly. The solution to get past this error is: 

    1.  Right click My Computer and click Properties
    2.  Click the Advanced tab
    3. Click the Settings button in the Performance section
    4. Make sure the radio button labeled “Turn on DEP for all processes and services except the ones I select” is checked
    5. Click Add at the bottom of the list
    6. Browse to the executale that they are going to run and select it
    7. Make sure the checkbox next to the executables name in the list is selected and click OK

    hope it will hep you.


    Regards, http://shwetamannjain.blogspot.com or https://shwetalodha.wordpress.com/

    Monday, June 4, 2012 3:49 AM
  • Hi Petr,

    In one shot, it looks like a true malloc bug.  Try a free trial of Compuware's devstudio heap checker, check your new/frees, and any memory allocations/leaks you perform.


    Regards, http://shwetamannjain.blogspot.com or https://shwetalodha.wordpress.com/

    Monday, June 4, 2012 4:34 AM
  • I am not sure why Marshal.ReadIntPtr is not throwing AccessViolationException. Also, why are you passing 1 to IntPtr? I think below is the code which you are looking for,

    class Program
    {
        [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += (sender, e) => Console.WriteLine("Unhandled: {0}", e.ExceptionObject);
            try
            {
                Test t = new Test();
                GCHandle handle = GCHandle.Alloc(t, GCHandleType.Pinned);
                IntPtr ip = handle.AddrOfPinnedObject();
    
                System.Runtime.InteropServices.Marshal.ReadIntPtr(ip);
                System.Runtime.InteropServices.Marshal.PtrToStructure(ip, typeof(Test));
            }
            catch (Exception e)
            {
                Console.WriteLine("Main: {0}", e);
            }
            Console.ReadLine();
        }
    
    }
    
    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    internal struct Test
    {
        public int X;
    }

    I hope this helps.


    Please mark this post as answer if it solved your problem. Happy Programming!

    Monday, June 4, 2012 5:15 AM
  • >  Also, why are you passing 1 to IntPtr?

    To simulate read operation from invalid location and show the AccessViolationException behavior difference between PtrToStructure and ReadIntPtr.

    The real code has a lot of PtrToStructure calls where pointers are read from deep nested structures so the code is error prone. When the AccessViolationException in a PtrToStructure call occurs I'd like to know the souce code line to find and fix the error (typically incorrectly aligned structure containing the IntPtr property etc.). It works for ReadIntPtr but not for PtrToStructure.

    Probably the only solution is to wrap Marshal.PtrToStructure method into my own method and pre-check whether I can read (via Marshal.ReadByte loop) from the IntPtr pointer for Marshal.SizeOf(T) size. The Marshal.ReadByte will throw AccessViolationException including stack information. But this is a bit awkward solution:

      public static T PtrToStructureSafe<T>(IntPtr ptr) where T : struct
      {
       Type t = typeof(T);
       int structSize = Marshal.SizeOf(t);
       for (int byteOffset = 0; byteOffset < structSize; byteOffset++)
        Marshal.ReadByte(ptr, byteOffset);
       return (T)Marshal.PtrToStructure(ptr, t);
      }


    Monday, June 4, 2012 12:26 PM
  • At least, it is a solution, right?

    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, June 5, 2012 7:13 AM
    Moderator
  • > At least, it is a solution, right?

    Technically it is a workaround but it is not answer to my initial question - why ? :-)

    • Edited by Petr Vones Tuesday, June 5, 2012 2:01 PM
    Tuesday, June 5, 2012 1:57 PM
  • 1. The AV exception thrown by Marshal.PtrToStructure is NOT handled by your UnhandledException handler.

    2. Marshal.ReadIntPtr() is a method that running on CLR, however, a call to Marshal.PtrToStructure() will be forwared to CLR, and executed inside CLR. In another words, your call to Marshal.PtrToStructure() interrupted the runtime, so the execution of managed code will be terminated immediately.

    3. As Karel suggested, you can capture a memory dump, and analysis the 1st chance exception's call stack to locate the root cause.


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Regards,
    Eric Yang
    Microsoft Online Community Support

    • Marked as answer by Petr Vones Monday, June 11, 2012 10:42 AM
    Monday, June 11, 2012 10:35 AM