none
How to convert an IntPtr to an object in C#? RRS feed

  • Question

  • Hi,

    I have got my hands on a managed object pointer (no its not a GCHandle) and want to convert it back to its true object. Before you ask:

    •  Yes this is unsafe
    •  GC might have moved the pointer to the managed object in the meantime rendering my pointer useless

    I have ensured that at this very moment I have a valid pointer so how can I make an object out of it?

    My current approach doesnot play well with the GC

       IntPtr pManagedObject = xxx
       object []arr = new object[1];
       IntPtr pArr = Marshal.UnsafeAddrOfPinnedArrayElement(arr,0);
       Marshal.WriteIntPtr(pArr,pManagedObject);

     

    The problem is that WriteIntPtr does write to a managed object which is not pinned. So it can happen that I write to an arbitrary memory location which could belong to a totally different object when a GC happens betwee UnsafeAddrOf.. and the WriteIntPtr call. Since GCHandle does not allow pinning of a managed object I am running out of options. All other attempts to Marshal it e.g. as a structure are prevented by the error message that the structure contains non blitable types. Are there any options which do play well with the GC?

    Yours,

      Alois Kraus

     

     

     

    Friday, July 2, 2010 1:28 PM

Answers

  • I did it! Below is the full code to create a Converter instance.

    It can be used like

    IntPtr pObject = xxx

    Converter<string> strConverter = new Converter<string>();

    string mangedObject = strConverter.ConvertFromIntPtr(pObject);


      class StaticModule
      {
        const string ModuleAssemblyName = "AloisDynamicCaster";
        public static Module UnsafeModule;
    
        static StaticModule()
        {
          AssemblyName assemblyName = new AssemblyName(ModuleAssemblyName);
          AssemblyBuilder aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
                                         AssemblyBuilderAccess.Run);
          ModuleBuilder mBuilder = aBuilder.DefineDynamicModule(ModuleAssemblyName);
          // set SkipVerification=true on our assembly to prevent VerificationExceptions which warn
          // about unsafe things but we want to do unsafe things after all.
          Type secAttrib = typeof(SecurityPermissionAttribute);
          var secCtor = secAttrib.GetConstructor(new Type[] { typeof(SecurityAction) });
          CustomAttributeBuilder attribBuilder = new CustomAttributeBuilder(secCtor,
            new object[] { SecurityAction.RequestMinimum },
            new PropertyInfo[] { secAttrib.GetProperty("SkipVerification", BindingFlags.Instance | BindingFlags.Public) },
            new object[] { true });
    
          aBuilder.SetCustomAttribute(attribBuilder);
          UnsafeModule = aBuilder.GetModule(ModuleAssemblyName);
        }
      }
     
    
      /// <summary>
      /// This class can convert any pointer to a managed object into a true object reference back.
      /// </summary>
      /// <typeparam name="T"></typeparam>
      public class Converter<T>
      {
        delegate U Void2ObjectConverter<U>(IntPtr pManagedObject);
        static Void2ObjectConverter<T> myConverter;
    
        // The type initializer is run every time the converter is instantiated with a different 
        // generic argument. 
        static Converter()
        {
          GenerateDynamicMethod();
        }
    
        static void GenerateDynamicMethod()
        {
          if (myConverter == null)
          {
            Console.WriteLine("Dynamic Method init");
            DynamicMethod method = new DynamicMethod("ConvertPtrToObjReference", typeof(T),
                    new Type[] { typeof(IntPtr) }, StaticModule.UnsafeModule);
            var gen = method.GetILGenerator();
            // Load first argument 
            gen.Emit(OpCodes.Ldarg_0);
            // return it directly. The Clr will take care of the cast!
            // this construct is unverifiable so we need to plug this into an assembly with 
            // IL Verification disabled
            gen.Emit(OpCodes.Ret);
            myConverter = (Void2ObjectConverter<T>)method.CreateDelegate(typeof(Void2ObjectConverter<T>));
          }
        }
    
        /// <summary>
        /// Convert a pointer to a managed object back to the original object reference
        /// </summary>
        /// <param name="pObj">Pointer to managed object</param>
        /// <returns>Object reference</returns>
        /// <exception cref="ExecutionEngineException">When the pointer does not point to valid CLR object. This can happen when the GC decides to move object references to new memory locations. 
        /// Beware this possibility exists all the time (although the probability should be very low)!</exception>
        public T ConvertFromIntPtr(IntPtr pObj)
        {
          return myConverter(pObj);
        }
      }

    Thanks for you help and time to point me to the right direction.

     

    Yours,

      Alois Kraus

     

    • Proposed as answer by eryang Wednesday, July 7, 2010 6:15 AM
    • Marked as answer by eryang Tuesday, August 24, 2010 8:32 AM
    Sunday, July 4, 2010 10:28 AM

All replies

  • Hi,

    I have got my hands on a managed object pointer (no its not a GCHandle) and want to convert it back to its true object. Before you ask:

    •  Yes this is unsafe
    •  GC might have moved the pointer to the managed object in the meantime rendering my pointer useless

    I have ensured that at this very moment I have a valid pointer so how can I make an object out of it?

    My current approach doesnot play well with the GC

       IntPtr pManagedObject = xxx
       object []arr = new object[1];
       IntPtr pArr = Marshal.UnsafeAddrOfPinnedArrayElement(arr,0);
       Marshal.WriteIntPtr(pArr,pManagedObject);

     

    The problem is that WriteIntPtr does write to a managed object which is not pinned. So it can happen that I write to an arbitrary memory location which could belong to a totally different object when a GC happens betwee UnsafeAddrOf.. and the WriteIntPtr call. Since GCHandle does not allow pinning of a managed object I am running out of options. All other attempts to Marshal it e.g. as a structure are prevented by the error message that the structure contains non blitable types. Are there any options which do play well with the GC?

    Yours,

      Alois Kraus

     

     

     


    This is a very unusual scenario and fraught with risks, somne of which you mention already.

    As you know an object declaration (like Form my_form_obj) is in-essence a pointer, it is a small variable in its own right that contains an address.

    What you need to do is in effect modify the address "field" that is in such a reference variable.

    If you could examine "my_form_obj" in memory you would see an actual machine address, that address will point to either NULL or an actual object instance in memory. So if you have an address of an instance already, you just need to write that address "into" the "my_form_obj" variable.

    There are ways I can think of, for doing this (its "just" a memcpy after all) but the'd require some pretty intricate experimentation, dynamic IL possibly mixed with unmanaged code could probably be contrived that would do this, but I'd be very worried about how the system would behave, for example would the GC know you have created this new reference to the object? I don't think it would.

    Is this absolutely necessary? may I ask how this question arose?

    Cap'n

     

    Friday, July 2, 2010 2:34 PM
  • The scenario is that I did get my hands dirty and I get from the current thread the last thrown exception object which is stored in the unmanged part of the Thread object. This does work actually very well but now I need to convert the pointer I did get into the managed object it actually is.

    I did notice in the SSCLI implementation an interface called IExecutionEngine which would also allow me to get the last thrown exception object but I am not aware of a possibility to get an instance of the interface. The guids from the rotor sources are not registered on my machine so I suspect this will get much more difficult.

     

      void STDMETHODCALLTYPE GetLastThrownObjectExceptionFromThread(void **ppvException);

    This method does look also interesting but I still need a way to transfer it back to the managed world.

     

    The options I see:

      - Can I get a notification before a GC starts (a full gc notification is not enough)?

     - Can I pin a reference type somehow?

     - Can I disable GC for a short amount of time? I know that this is possible since GC is disabled for certain threads in specific scenarios.

     

    Yours,

      Alois Kraus

     

    Friday, July 2, 2010 10:10 PM
  • using System;
    using System.Runtime.InteropServices;
    
    class Program
    {
      static void Main(string[] args)
      {
        IntPtr pManagedObject;
    
        // Get managed object as IntPtr
        {
          Program program = new Program();
          pManagedObject = GCHandle.ToIntPtr(GCHandle.Alloc(program, GCHandleType.Normal));
        }
    
        // Return it back to managed reference
        {
          GCHandle handle = GCHandle.FromIntPtr(pManagedObject);
          Program program = (Program)handle.Target;
          handle.Free();
          Console.WriteLine(program);
        }
      }
    
      public override string ToString()
      {
        return "My Program";
      }
    }
    
    Saturday, July 3, 2010 1:45 AM
  • Hi Tergiver,

    the solution you proposed assumes that IntPtr points to a GCHandle. That is not my case. I have a real pointer to a managed CLR object. It is the real address like Windbg with the SOS extension does display. I did try GCHandle.FromIntPtr already and was greeted with an ExecutionEngineException because my IntPtr was not a GCHandle.

    The other problem is that the GCHandle does not pin the pointer. But at some point I need to write the object address to a memory location that does not change from GC to GC.

    Yours,

      Alois Kraus

     

    Saturday, July 3, 2010 12:43 PM
  • OK

    Try playing with a DynamicMethod. Write one that accepts the IntPtr or void * (if this helps in the IL), also pass in the Type of the object.

    In your IL try to use the OpCodes.Castclass opcode.

    This will expect an object reference (supplied by you) and then do a cast and return a real ref to the object.

    The fiddly bit (which I don't have time to look into now) will be to use IL to manipulate the passed IntPtr or void * into a type O (object reference), if you can do that, the Castclass will work and you will indeed have a true object ref.

    Ldarg_a may help here also, but I'm just thinking out loud.

    Cap'n

     

    Saturday, July 3, 2010 2:07 PM
  • the solution you proposed assumes that IntPtr points to a GCHandle. That is not my case.


    I thought from your comments that you didn't know how to create a GCHandle on a reference object (Normal). There is no need to pin it if you have a GCHandle and are accessing it from managed code.

    I thought maybe you could alter your code to create a GCHandle at the source.

    Saturday, July 3, 2010 2:23 PM
  • The fiddly bit (which I don't have time to look into now) will be to use IL to manipulate the passed IntPtr or void * into a type O (object reference)...

    That's the sticky point. I'm not sure it's possible, even in IL. There's a reason it's called "managed code".
    Saturday, July 3, 2010 2:25 PM
  • However.. Windows Forms must use a Thunk to deal with WndProc calls. Hmm.. where is that code located...
    Saturday, July 3, 2010 2:32 PM
  • However.. Windows Forms must use a Thunk to deal with WndProc calls. Hmm.. where is that code located...

    It doesn't. It uses a lookup table like MFC. That might tell you something.
    Saturday, July 3, 2010 2:46 PM
  • Actually, what it does is use a delegate (there is a handle map, but that appears to be used only for Control.FromHandle).

    I have no idea what mechanism the CLR uses to implement instance delegates. You can pass one to an unmanaged function as a callback and somehow magically an instance call gets made. Is it done using a Thunk? I don't know. The Mono source might be useful to find this mechanism in.

    However, the CLR is not managed code, so it can cast any pointer to anything it likes.

    Saturday, July 3, 2010 4:43 PM
  • Thanks I will try it out.

     

    Yours,

       Alois Kraus

     

    Saturday, July 3, 2010 8:19 PM
  • There are a number of methods inside the CLR for converting an address to a CLR reference. All of these are inaccessable unless you are an official Framework assembly. This is further evidence that it can only be done inside the CLR.
    Saturday, July 3, 2010 8:23 PM
  • That sounds bad. Are there specialized IL codes used or did you have a look at the "real" CLR sources?

     

    Yours,

      Alois Kraus

     

    Saturday, July 3, 2010 9:20 PM
  • I haven't seen any CLR source yet. I've been poking around in the System namespace (for an unrelated question) and discovered several CLR exported methods that take a void* and return object with names like InternalGetReference. If you add an export declaration and attempt to call one of them, you get an exception because your assembly is not a system assembly.
    Saturday, July 3, 2010 9:29 PM
  • There are a number of methods inside the CLR for converting an address to a CLR reference. All of these are inaccessable unless you are an official Framework assembly. This is further evidence that it can only be done inside the CLR.


    You can definitely do what you want with a DynamicMethod.

    You can dynamically create a method that accepts a pointer and returns an object ref, there are IL opcodes that do this. I say dynamically create it, because you can code a generic address converter generator method that takes a <T> for the type. This will create and return a matching delegate instance: object CvrtPtrToRef<T>(void *); or perhaps object CvrtPtrToRef<T>(IntPtr);

    So your dynamic method basically loads a pointer and converts it to an object reference (see Opcodes.Ldind_Ref for some insight into this).

    Once you have the delegate its easy, you just call it and cast its returned value, in fact you could code all this so that it returns a T thereby eliminating the need to do any cast even.

    I've coded stuff very much like this (and rather more complicated) so I am almost 100% certain this is possible.

    Cap'n

     

     

     

    Sunday, July 4, 2010 1:19 AM
  • I am still trying to get it working. I have found a blog entry which seems to cover a similar topic

    http://www.lordzoltan.org/blog/post/Passing-ref-parameters-in-a-params-object-array.aspx

    but so far I was not able to get it working. This IL generation stuff is very complex to debug.

    Before this I tried to generate a TypedReference and modify its internal Value IntPtr which seemed quite easy to do. But Reflection does break here since I cannot set the value since any instance of TypedReference cannot be cast to object which prevents calling .SetValue(object, value).

    About TypedReference there is a nice CP article online

    http://www.codeproject.com/KB/dotnet/pointers.aspx

    which raised some hope but I think I will need to muddle through the IL stuff and enable SkipVerification on the dynamic method to do my stuff.

     

    Yours,

     Alois Kraus

     

    Sunday, July 4, 2010 9:06 AM
  • I did it! Below is the full code to create a Converter instance.

    It can be used like

    IntPtr pObject = xxx

    Converter<string> strConverter = new Converter<string>();

    string mangedObject = strConverter.ConvertFromIntPtr(pObject);


      class StaticModule
      {
        const string ModuleAssemblyName = "AloisDynamicCaster";
        public static Module UnsafeModule;
    
        static StaticModule()
        {
          AssemblyName assemblyName = new AssemblyName(ModuleAssemblyName);
          AssemblyBuilder aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
                                         AssemblyBuilderAccess.Run);
          ModuleBuilder mBuilder = aBuilder.DefineDynamicModule(ModuleAssemblyName);
          // set SkipVerification=true on our assembly to prevent VerificationExceptions which warn
          // about unsafe things but we want to do unsafe things after all.
          Type secAttrib = typeof(SecurityPermissionAttribute);
          var secCtor = secAttrib.GetConstructor(new Type[] { typeof(SecurityAction) });
          CustomAttributeBuilder attribBuilder = new CustomAttributeBuilder(secCtor,
            new object[] { SecurityAction.RequestMinimum },
            new PropertyInfo[] { secAttrib.GetProperty("SkipVerification", BindingFlags.Instance | BindingFlags.Public) },
            new object[] { true });
    
          aBuilder.SetCustomAttribute(attribBuilder);
          UnsafeModule = aBuilder.GetModule(ModuleAssemblyName);
        }
      }
     
    
      /// <summary>
      /// This class can convert any pointer to a managed object into a true object reference back.
      /// </summary>
      /// <typeparam name="T"></typeparam>
      public class Converter<T>
      {
        delegate U Void2ObjectConverter<U>(IntPtr pManagedObject);
        static Void2ObjectConverter<T> myConverter;
    
        // The type initializer is run every time the converter is instantiated with a different 
        // generic argument. 
        static Converter()
        {
          GenerateDynamicMethod();
        }
    
        static void GenerateDynamicMethod()
        {
          if (myConverter == null)
          {
            Console.WriteLine("Dynamic Method init");
            DynamicMethod method = new DynamicMethod("ConvertPtrToObjReference", typeof(T),
                    new Type[] { typeof(IntPtr) }, StaticModule.UnsafeModule);
            var gen = method.GetILGenerator();
            // Load first argument 
            gen.Emit(OpCodes.Ldarg_0);
            // return it directly. The Clr will take care of the cast!
            // this construct is unverifiable so we need to plug this into an assembly with 
            // IL Verification disabled
            gen.Emit(OpCodes.Ret);
            myConverter = (Void2ObjectConverter<T>)method.CreateDelegate(typeof(Void2ObjectConverter<T>));
          }
        }
    
        /// <summary>
        /// Convert a pointer to a managed object back to the original object reference
        /// </summary>
        /// <param name="pObj">Pointer to managed object</param>
        /// <returns>Object reference</returns>
        /// <exception cref="ExecutionEngineException">When the pointer does not point to valid CLR object. This can happen when the GC decides to move object references to new memory locations. 
        /// Beware this possibility exists all the time (although the probability should be very low)!</exception>
        public T ConvertFromIntPtr(IntPtr pObj)
        {
          return myConverter(pObj);
        }
      }

    Thanks for you help and time to point me to the right direction.

     

    Yours,

      Alois Kraus

     

    • Proposed as answer by eryang Wednesday, July 7, 2010 6:15 AM
    • Marked as answer by eryang Tuesday, August 24, 2010 8:32 AM
    Sunday, July 4, 2010 10:28 AM
  • Nice. It seems obvious in hind-sight, but it never would have occurred to me to simply load the address and return it.
    Sunday, July 4, 2010 2:30 PM
  • I was quite desperate so I tried also the unreasonable. That will enable a cool feature to get my hands on an exception in the finally block while stack unwinding and print it in my tracer class which is dispsed in a finally block due to the using statement.

     

    Yours,

     Alois Kraus

     

    Sunday, July 4, 2010 3:42 PM
  • I have now a tracing library in place which can be used like this

     

      void SomeMethod()
      {
       using (Tracer t = new Tracer(myType, "SomeMethod"))
       {
        SomeOtherMethod();
       }
      }
    
      private void SomeOtherMethod()
      {
       using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
       {
        FaultyMethod();
       }
      }
    
      private void FaultyMethod()
      {
       throw new NotImplementedException("Hi this a fault");
      }
    

     

    It will print the exception in the Dispose method of Tracer in SomeOtherMethod so you can easily diagnose what exception was thrown.

     

    The library and its description can be found there

    Yours, 

          Alois Kraus

     

     

    Sunday, July 4, 2010 7:00 PM
  • How does that improve on what we already have?

      try
      {
        SomeMethod();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
        throw;
      }
    
    Sunday, July 4, 2010 9:09 PM
  • Well try it. Catching exceptions for the purpose of tracing is not a good idea after all. Why should I bother writing catch handlers everywhere without actually handling the exception? In my opinion this pattern should be banned. Lets try  with "what we already have" and lets see how good it gets:

        private void SomeOtherMethod()
        {
          using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
          {
            FaultyMethod();
          }
        }
    
        private void SomeOtherMethod()
        {
          using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
          {
            try
            {
              FaultyMethod();
            }
            catch (Exception ex)
            {
              t.Error(ex);
            }
          }
        }
    

    I am not a big fan of repetitive code which is error prone. It looks right but did you notice in the sample with the exception that I did swallow the exception? Perhaps this was my intention perhaps not.  Then I need to add a throw but some people do a throw ex which will restart the stack trace. Writing error handling constructs which do not handle the error are by definition an error. When you want to keep your code transparent for exceptions you should have no need to catch exceptions. A Thread.CurrentThread.LastThrownException would be cool in the next .NET Framework version.

    Yours,

      Alois Kraus

     

     

     

     

    Sunday, July 4, 2010 9:28 PM
  • There's no difference between these two in the case where an exception is thrown. Both of them catch the exception.

      try
      {
        SomeMethod();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
        throw;
      }
    
      try
      {
        SomeMethod();
      }
      finally
      {
        // dump exception from stack
      }
    

     

    Sunday, July 4, 2010 11:15 PM
  • I think you are debating at IL level. Yes the finally block catches all exceptions and rethrows them afterwards. But the difference is that when you are not inside a catch block you have no access to the current exception. And you certainly do not want to clutter your code with try/catch/finally blocks all the time. A using statement is much better and composable than to explicitely code every case by hand.

    Yours,

      Alois Kraus

     

    Monday, July 5, 2010 10:46 AM
  •  

    Hi Alois,

     

    Glad to see that you have got your case resolved, by the way, if you have no other concern on this issue, you may close this thread by marking useful replies as answers, this can be beneficial to other community members reading the thread.


    Sincerely,
    Eric
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, July 7, 2010 6:19 AM
  • Hi Alois,

        I get that mangedObject is NULL .

    My code as below, I would like ask for your help to fix it:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.Security.Permissions;
    
    namespace MySpace
    {
      class StaticModule
      {
        const string ModuleAssemblyName = "AloisDynamicCaster";
        public static Module UnsafeModule;
    
        static StaticModule()
        {
          AssemblyName assemblyName = new AssemblyName(ModuleAssemblyName);
          AssemblyBuilder aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
                          AssemblyBuilderAccess.Run);
          ModuleBuilder mBuilder = aBuilder.DefineDynamicModule(ModuleAssemblyName);
          // set SkipVerification=true on our assembly to prevent VerificationExceptions which warn
          // about unsafe things but we want to do unsafe things after all.
          Type secAttrib = typeof(SecurityPermissionAttribute);
          ConstructorInfo secCtor = secAttrib.GetConstructor(new Type[] { typeof(SecurityAction) });
          CustomAttributeBuilder attribBuilder = new CustomAttributeBuilder(secCtor,
           new object[] { SecurityAction.RequestMinimum },
           new PropertyInfo[] { secAttrib.GetProperty("SkipVerification", BindingFlags.Instance | BindingFlags.Public) },
           new object[] { true });
    
          aBuilder.SetCustomAttribute(attribBuilder);
          UnsafeModule = aBuilder.GetModule(ModuleAssemblyName);
        }
      }
    
      /// <summary>
      /// This class can convert any pointer to a managed object into a true object reference back.
      /// </summary>
      /// <typeparam name="T"></typeparam>
      public class Converter<T>
      {
        delegate U Void2ObjectConverter<U>(IntPtr pManagedObject);
        static Void2ObjectConverter<T> myConverter;
    
        // The type initializer is run every time the converter is instantiated with a different 
        // generic argument. 
        static Converter()
        {
          GenerateDynamicMethod();
        }
    
        static void GenerateDynamicMethod()
        {
          if (myConverter == null)
          {
            Console.WriteLine("Dynamic Method init");
            DynamicMethod method = new DynamicMethod("ConvertPtrToObjReference", typeof(T),
                new Type[] { typeof(IntPtr) }, StaticModule.UnsafeModule);
            ILGenerator gen = method.GetILGenerator();
            // Load first argument 
            gen.Emit(OpCodes.Ldarg_0);
    
            // return it directly. The Clr will take care of the cast!
            // this construct is unverifiable so we need to plug this into an assembly with 
            // IL Verification disabled
            gen.Emit(OpCodes.Ret);
            myConverter = (Void2ObjectConverter<T>)method.CreateDelegate(typeof(Void2ObjectConverter<T>));
          }
        }
    
        /// <summary>
        /// Convert a pointer to a managed object back to the original object reference
        /// </summary>
        /// <param name="pObj">Pointer to managed object</param>
        /// <returns>Object reference</returns>
        /// <exception cref="ExecutionEngineException">When the pointer does not point to valid CLR object. This can happen when the GC decides to move object references to new memory locations. 
        /// Beware this possibility exists all the time (although the probability should be very low)!</exception>
        public T ConvertFromIntPtr(IntPtr pObj)
        {
          return myConverter(pObj);
        }
      }
    }
    

    Sunday, September 26, 2010 5:31 PM
  • Hi , 

    I have the same question with Alois, I'm trying to get an known class by using hWnd which is got from FindWindowEx.

    This known class contains some information that I need, but the information is not able to get by FindWindowEx/SendMessage

    I did try the code from Alois, Win7 tells me "It is protected memory".

     

    Anyone know how to deal with this?

     

    thanks.




    Tuesday, August 9, 2011 4:10 PM
  • I know, I bit late :) but anyway maybe it will be helpful for others. I have found solution and it works in my case -

    public static class Converter
        {
            public static unsafe T GetInstance<T>(IntPtr pointer)
            {
                try
                {
                    var fakeInstance = default(T);
                    TypedReference typedReference = __makeref(fakeInstance);
                    *(IntPtr*)(&typedReference) = pointer;
                    T instance = (T) __refvalue(typedReference,T);
                    return instance;
                }
                catch
                {
                    return default(T);
                }
            }
        }




    Wednesday, December 11, 2013 9:31 PM
  • @Andrei: Thats a nice one. You do not need the catch clause since it will cause an ExecutionEngineException if you are caught be the GC at the wrong moment. If you can avoid it you should access the data via a GCHandle. The CLR ObjRef type is in reality a GCHandle (although it is simply a pointer pointer) where you can stop dereferencing the GCHandle and use instead

    GCHandle.FromIntPtr

    which is a safe operation even when the GC is moving things around. I had my experiences with this stuff and know much more about managed Heap corruptions and how to debug than I ever wanted to know ;-).

    Yours,

     Alois Kraus

    Wednesday, December 11, 2013 10:11 PM