2010-03-22 13 views
31

¿Cuáles son las consecuencias (positivas/negativas) de utilizar la palabra clave insegura en C# utilizar punteros? Por ejemplo, ¿qué pasa con la recolección de basura, cuáles son las ganancias/pérdidas de rendimiento, cuáles son las ganancias/pérdidas de rendimiento en comparación con la gestión de memoria manual de otros idiomas, cuáles son los peligros, en qué situación es realmente justificable hacer uso de este lenguaje? característica, ¿es más largo para compilar ...?C# gestión de la memoria: la palabra clave inseguro y punteros

Respuesta

25

Como ya mencionó Conrad, hay algunas situaciones donde el acceso inseguro a la memoria en C# es útil. No hay ya que muchos de ellos, pero hay algunos:

  • Manipular con Bitmap es casi un ejemplo típico donde se necesita un poco de rendimiento adicional que se puede obtener mediante el uso de unsafe.

  • Interoperabilidad con la API de más edad (como WinAPI o nativo de C/C++ DLL) es otra área en la unsafe puede ser muy útil - por ejemplo, es posible que desee llamar a una función que toma/devuelve un puntero no administrado.

Por otro lado, se puede escribir la mayoría de las cosas utilizando Marshall class, que oculta muchas de las operaciones inseguras dentro de las llamadas de método. Este será un poco más lento, pero es una opción si desea evitar el uso unsafe (o si está usando VB.NET, que no tiene unsafe)

consecuencias positivas: Por lo tanto, el principal Las consecuencias positivas de la existencia de unsafe en C# es que puedes escribir un código más fácilmente (interoperabilidad) y puedes escribir un código de manera más eficiente (manipulando con mapa de bits o tal vez algunos cálculos numéricos pesados ​​utilizando matrices, aunque no estoy tan seguro sobre el segundo)

consecuencias negativas: Por supuesto, hay un cierto precio que hay que pagar por el uso unsafe:

  • no verificable código: C# código que se escribe utilizando los unsafe características se convierte en no -verificable, lo que significa que su código podría comprometer el tiempo de ejecución de cualquier manera. Este no es un gran problema en un escenario de plena confianza (por ejemplo, aplicación de escritorio no restringida); simplemente no tiene todas las garantías agradables de .NET CLR. Sin embargo, no puede ejecutar la aplicación en un entorno restringido, como alojamiento web público, Silverlight o confianza parcial (por ejemplo, aplicación que se ejecuta desde la red).

  • Recolector de basura también debe tener cuidado cuando usa unsafe. GC generalmente se permite reubicar objetos en el montón administrado (para mantener la memoria desfragmentada). Cuando toma un puntero a algún objeto, necesita usar la palabra clave fixed para decirle al GC que no puede mover el objeto hasta que termine (lo que probablemente podría afectar el rendimiento de la recolección de basura, pero por supuesto, dependiendo del escenario exacto) .

Mi suposición de que si C# no tiene que interoperar con código antiguo, probablemente no apoyar unsafe (investigación y proyectos como singularidad que intentan crear un sistema operativo más verificable basado en lenguajes administrados definitivamente no permitir usnsafe código). Sin embargo, en el mundo real, unsafe es útil en algunos casos (raros).

4

Para citar Profesional C# 2008:

"Las dos razones principales para utilizar punteros son:

  1. compability hacia atrás - A pesar de todas las facilidades proporcionadas por el .NET a en tiempo de ejecución aún es posible llamar a funciones nativas de la API de Windows y para algunas operaciones esta puede ser la única forma de realizar su tarea . Estas funciones API generalmente son escritas en C y a menudo requieren punteros como parámetros. Sin embargo, en muchos casos es posible escribir la declaración DllImport de una manera que evita el uso de punteros; por ejemplo, mediante el uso de la clase System.IntPtr.
  2. Rendimiento - En las ocasiones en que la velocidad es de la mayor importancia , el puntero puede proporcionar una ruta para optimizar el rendimiento. Si sabe lo que está haciendo, puede asegurarse de que se acceda a los datos manipulados de la manera más eficiente. Sin embargo, tenga en cuenta que, con más frecuencia que no, hay otras áreas de su código en el que puede hacer necesario mejorar el rendimiento sin volver a conectar los punteros. Trate de usar un perfilador código para buscar los cuellos de botella en el código - uno viene con Visual Studio 2008. "

Y si utiliza puntero de su código requerirá mayor palanca de confianza para ejecutar y si el usuario no quiera que su código no se ejecutará

y se envuelve con una última cita:.

"Estamos firmemente consejos contra el uso de punteros innecesariamente becau sí se no sólo será más difícil de escribir y depurar, pero también fallará la memoria cheques tipo de seguridad impuestas por la CLR."

+0

¿Puede publicar los enlaces para su referencia? – Alerty

+1

Es un libro que compré: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2008.productCd-0470191376.html –

+0

¡Está bien! Gracias: D – Alerty

8

que le puede dar una situación en la que valía la pena usar :

Tengo que generar un mapa de bits píxel por píxel. Drawing.Bitmap.SetPixel() es demasiado lento. Así que construyo mi propio Array administrado de datos de mapa de bits, y uso unsafe para obtener el IntPtr para Bitmap.Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr).

+1

Sí, los mapas de bits aún no tienen una rápida API 'administrada'. –

1

La recolección de basura es ineficaz con objetos de larga vida. El recolector de basura de .Net funciona mejor cuando la mayoría de los objetos se lanzan con bastante rapidez, y algunos objetos "viven para siempre"."El problema es que los objetos de vida más larga solo se liberan durante las recolecciones de basura completas, lo que implica una importante penalización del rendimiento. En esencia, los objetos de larga vida pasan rápidamente a la generación 2.

(Para obtener más información, es posible que desee leer en el recolector de basura generacional de .Net: http://msdn.microsoft.com/en-us/library/ms973837.aspx)

En situaciones donde los objetos, o el uso de la memoria en general, va a durar mucho tiempo, la administración manual de memoria rendirá mejor rendimiento porque puede ser liberada al sistema sin requiere una colección completa de basura.

Implementación de algún tipo de sistema de administración de memoria basado en una sola gran la matriz de bytes, las estructuras y mucha aritmética del puntero, teóricamente podrían aumentar el rendimiento en situaciones donde los datos se almacenarán en la memoria RAM durante mucho tiempo.

Lamentablemente, no conozco una buena forma de hacer la gestión de memoria manual en .Net para objetos que durarán mucho tiempo. Esto básicamente significa que las aplicaciones que tienen datos de larga duración en la RAM perderán periódicamente su capacidad de respuesta cuando ejecuten una recolección completa de basura de toda la memoria.

Cuestiones relacionadas