una sharp qué que operaciones objetos objeto método memoria imprimir direccion declarar con clases clase c# mono garbage-collection

sharp - ¿ en c# qué es método?



Obtener la dirección de memoria del objeto.NET(C#) (4)

Estoy tratando de rastrear un error en el tiempo de ejecución mono donde una variable parece estar asignada a un objeto válido, y luego es reasignada a un objeto falso, específicamente

//early in code I allocate, fine var o = new object(); // valid allocation // later in code this is called, not fine lock(o) // <- is triggering bug due to "o" now referencing a nonsense memory location.

Me gustaría saber cuándo la referencia a "o" se vuelve absurda, y para hacer esto estoy buscando una forma de determinar la dirección de "o" en varios puntos de tiempo dentro del código C #. Sé que es similar a otras preguntas con respuestas "no hagas que haya un GC", pero el GC no funciona, así que necesito una solución alternativa.

¿Alguien sabe cómo puedo determinar la dirección de un objeto mono en C #? Estoy bien para vincular en código no administrado o lo que sea. (Cualquier otra pista sobre cómo diagnosticar el problema principal es apreciado).


Debería poder usar el constructo GCHandle para lograr esto.

GCHandle objHandle = GCHandle.Alloc(obj,GCHandleType.WeakTrackResurrection); int address = GCHandle.ToIntPtr(objHandle).ToInt32();

Donde ''obj'' es el objeto cuya dirección estás tratando de obtener.


En general, no puede obtener la dirección de un objeto gestionado en código administrado. Si el objeto tiene un campo como un int, podría tomar su dirección con la instrucción C # fija y luego tendría un puntero dentro del objeto. Para fines de depuración, puede hacer algunas suposiciones y obtener el desplazamiento al puntero base del objeto (en plataformas de 32 bits, el tamaño del encabezado del objeto en mono es de 8 bytes, 16 bytes en arquitecturas de 64 bits, en este momento).

Sin embargo, su informe de error afirma que está utilizando el recopilador Boehm, y ese recopilador no mueve objetos en la memoria, el error podría deberse a una corrupción de memoria no relacionada, al objeto incorrectamente liberado o algún otro error lógico en el GC (No estoy seguro de que el tamaño cero que señaló sea relevante, ya que un objeto administrado tiene al menos el encabezado de 8 a 16 bytes).


Resulta que esto no es posible en .NET directamente, pero se puede lograr alterando el código de tiempo de ejecución mono. Para crear un método C # que pueda leer la dirección de la memoria, realice los siguientes cambios en el código fuente mono:

Alter gc-internal.h para agregar

gpointer ves_icall_System_GCHandle_GetAddrOfObject (MonoObject *obj) MONO_INTERNAL;

Altere gc.c para agregar:

gpointer ves_icall_System_GCHandle_GetAddrOfObject (MonoObject *obj) { return (char*)obj; }

Altere GCHandle.cs para agregar:

MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static IntPtr GetAddrOfObject(object obj); public static IntPtr AddrOfObject(object o) { IntPtr res = GetAddrOfObject(o); return res; }

Alter icall-def.h para agregar

ICALL(GCH_6, "GetAddrOfObject", ves_icall_System_GCHandle_GetAddrOfObject)

Tenga en cuenta que estos deben estar en orden, así que agréguelo por encima de la línea GetAddrOfPinnedObject Rebuild

Finalmente, llámalo desde C #

for (int i = 0; i < 100; i++) { object o = new object (); var ptr = GCHandle.AddrOfObject (o); Console.WriteLine ("Address: " + ptr.ToInt64().ToString ("x")); }


Mis alternativas ... También @ Esta pregunta similar

#region AddressOf /// <summary> /// Provides the current address of the given object. /// </summary> /// <param name="obj"></param> /// <returns></returns> [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static System.IntPtr AddressOf(object obj) { if (obj == null) return System.IntPtr.Zero; System.TypedReference reference = __makeref(obj); System.TypedReference* pRef = &reference; return (System.IntPtr)pRef; //(&pRef) } /// <summary> /// Provides the current address of the given element /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static System.IntPtr AddressOf<T>(T t) //refember ReferenceTypes are references to the CLRHeader //where TOriginal : struct { System.TypedReference reference = __makeref(t); return *(System.IntPtr*)(&reference); } [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] static System.IntPtr AddressOfRef<T>(ref T t) //refember ReferenceTypes are references to the CLRHeader //where TOriginal : struct { System.TypedReference reference = __makeref(t); System.TypedReference* pRef = &reference; return (System.IntPtr)pRef; //(&pRef) } /// <summary> /// Returns the unmanaged address of the given array. /// </summary> /// <param name="array"></param> /// <returns><see cref="IntPtr.Zero"/> if null, otherwise the address of the array</returns> [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static System.IntPtr AddressOfByteArray(byte[] array) { if (array == null) return System.IntPtr.Zero; fixed (byte* ptr = array) return (System.IntPtr)(ptr - 2 * sizeof(void*)); //Todo staticaly determine size of void? } #endregion