2010-03-22 9 views
37

Estoy tratando de encontrar una pérdida de memoria usando el generador de perfiles de memoria de hormigas, y me he encontrado en un nuevo término:¿Qué son los objetos anclados?

Objetos fijados.

¿Puede alguien darme una buena explicación & simple acerca de lo que son estos objetos, ¿cómo puedo pinn/Unpinn objetos, y detectar quién fijó los objetos?

Gracias

Respuesta

44

Un objeto inmovilizado es aquel que no puede moverse. El recolector de basura normalmente compacta la memoria porque mueve todos los objetos a "uno o más clústeres". Esto es para crear grandes porciones de espacio libre.

Esto significa básicamente que si alguien más (fuera) tiene un puntero a la dirección de memoria de un objeto, esto puede apuntar a contenido aleatorio, ya que el objeto se ha movido.

La fijación de un objeto le indica al GC que NO LA MUEVA. Esto normalmente es inútil y SÓLO tiene sentido cuando se trabaja con punteros, como cuando se utiliza PInvoke. A veces es necesario ingresar una dirección en una estructura (en el término de diseño de la memoria), y si eso se implementa en una clase, debe anclarlo.

Para respuesta concreta:

  • No se puede averiguar quién cubrió un obiect.
  • La fijación se realiza con la instrucción FIJA. Esto solo está permitido en un código no seguro.

Comprobar:

http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

+11

No es necesario que sea inseguro. Como puede ver: Buffer = new byte [imageSize]; GCHandle gCBuffer = GCHandle.Alloc (Buffer, GCHandleType.Pinned); – Pedro77

+1

Sin embargo, requiere plena confianza, lo que es equivalente a un código inseguro. – usr

18

Un objetivo fijado es uno que no puede ser movido alrededor por el recolector de basura, es decir, su dirección se tiene que mantener la misma porque otra persona, por lo general alguna pieza de código no administrado, depende de que el objeto en una dirección de memoria definida.

Por lo general, el recolector de basura tiene libertad para reubicar objetos en la memoria. En el código administrado, como el recolector de basura tiene la capacidad de acceder a todas las referencias, puede reasignar libremente un objeto a una ubicación diferente y luego actualizar todas las referencias a ese objeto para que el proceso sea transparente para el código en ejecución. De esta forma, el GC tiene la capacidad de organizar mejor la memoria del programa y compactarla si es necesario.

Cuando un objeto no administrado está interactuando con su código (en secciones inseguras), puede surgir una situación donde hay un puntero en alguna parte de un elemento de su código & thinsp; - & thinsp; por ejemplo, en una pieza de memoria tratada en su código que está siendo manejado por una llamada COM externa. Esta memoria no se puede reasignar porque la llamada COM espera que el objeto esté en una dirección determinada y, por lo tanto, si se movió, el GC no tendría manera de notificar al objeto COM de ese cambio, lo que daría como resultado un acceso violación o peor.

5

Con el fin de precisar los objetos se puede utilizar la palabra clave fixed:

La declaración fija impide que el recolector de basura de reubicación de una variable móvil . La instrucción fija solo está permitida en un contexto inseguro .

Un ejemplo que he visto antes es dividir un valor largo en bytes para que pueda codificarse en una clave de serie. Esto se hizo en un contexto unsafe para obtener el puntero. Los errores intermitentes comenzaron a ocurrir porque la recolección de basura ocurriría a mitad del proceso de obtener los bytes individuales. El valor se reubicaría y nos quedamos con la mitad de los bytes correctos, la mitad de los bytes de basura.

La solución para nosotros fue utilizar la clase BitConverter. Si observa el código subyacente de la clase BitConverter, verá que usa la palabra clave fija para fijar la matriz de bytes mientras obtiene los bytes de la variable.

4

Un objetivo fijado es uno que tiene un lugar establecido en la memoria.

Normalmente, el recolector de basura compactará el montón administrado, que cambia la ubicación de los objetos en la memoria. Si tiene algún código no administrado que hace referencia a algún objeto C# que haya creado, es posible que desee poder hacer referencia a la ubicación de la memoria en forma absoluta. Fijar el objeto le permite hacer esto con certeza.

Se pueden crear utilizando el fixed declaración: http://msdn.microsoft.com/en-us/library/f58wzh21%28VS.80%29.aspx

6

objetos anclados se usan cuando se comunica con un código no administrado. En el código administrado, el recolector de basura puede mover libremente los bloques de memoria, ya que conoce todas las referencias al bloque de memoria y puede actualizarlos en consecuencia.

Cuando se comunica con el código no administrado (por ejemplo, Win-API), los punteros a datos o búferes a menudo se pasan como argumento. Si el recolector de basura fuera libre de mover esos datos, los punteros se volverían inválidos de repente. A medida que el puntero se transfiere a un código no administrado, el GC no puede actualizar el puntero, ni siquiera saber dónde se usa. Para evitar que la memoria se mueva y asegúrese de que los datos permanecen en el lugar conocido por el puntero del código no administrado, el objeto puede ser con pines.

6

La razón por la que podría pintar un objeto es si está realizando llamadas al código no administrado.

Cuando se ejecuta el recolector de elementos no utilizados puede eliminar un objeto que ya no se necesita. Esto deja un "agujero" de espacio libre en el montón. El GC luego compacta el montón moviendo los objetos restantes para asegurarse de que el espacio libre esté en un bloque continuo (un poco como desfragmentar el disco duro).

También actualiza todas las referencias (en el código administrado) a cualquier objeto que se haya movido como parte de la compactación.

Si está trabajando con código no administrado (por ejemplo, algún C++ externo) y le da un puntero a un objeto, el GC no tiene forma de indicar el código no administrado que el objeto ha movido después de haberse ejecutado. Por lo tanto, puede marcar el objeto que comparte con el código externo como fijado para que no tenga el problema de que el puntero se vuelva inválido.

Cuestiones relacionadas