Pregunta

Estoy teniendo problemas con una pérdida de memoria lenta en mi modo mixto C ++ aplicación .NET / CLR.

(Es bibliotecas estáticas C ++ nativo vinculado en una VS2008 C ++ / CLR Windows Forms aplicación con la configuración del compilador "/ CLR")

El comportamiento típico: aplicación comienza a utilizar 30 MB de memoria (privado). A continuación, pérdidas de memoria slowish, por ejemplo un MB cada hora cuando se ejecuta bajo una fuerte carga simulada. Esto simula la aplicación de ser vivo durante días o semanas.

He intentado usar varias herramientas para localizar pérdidas de memoria que incluye tanto el material de depuración CRT que viene con las librerías de Visual Studio CRT. También he utilizado una herramienta de detección de fugas comercial ( "Memoria Validador").

Los dos informes insignificantes pérdidas de memoria en el apagado (unas pocas entradas menores que equivalen a unos pocos KB que no me preocupa). Además, puedo ver que cuando se ejecuta la memoria rastreado no parece equivaler a que gran parte (por lo que no creo que es sólo la memoria que se está celebrando en libertad y sólo en la salida aplicación). Me sale alrededor de 5 MB de memoria la lista (de total> 30 MB).

La herramienta (Validador de memoria) está configurado para realizar un seguimiento de todo el uso de la memoria (incluyendo malloc, nuevo, la asignación de memoria virtual y un montón de otros tipos de asignación de memoria). Básicamente, todos los ajustes de la memoria que quiere ha sido seleccionado.

La imagen .NET informa que está utilizando alrededor de 1,5 MB de memoria (de perfmon).

Aquí hay un poco de información final: tenemos una versión de la aplicación que se ejecuta como una aplicación de consola nativa (puramente nativa - CLR no en todos). Esto es 95% el mismo que el modo mixto, excepto sin el material de interfaz de usuario. Esto no parece perder memoria en absoluto, y picos en alrededor de bytes privados de 5 MB.

Así que básicamente lo que estoy tratando de conseguir a través de este caso es que yo no creo que ninguno de código nativo tiene una fuga de memoria.

Otra pieza del rompecabezas: I encontraron esta que se refiere a las pérdidas de memoria en aplicaciones de modo mixto cuando la orientación 2,0 marco (que soy): http://support.microsoft.com/kb/961870

Por desgracia, los detalles son exasperantemente escasa así que no estoy seguro de si es relevante. Yo probé la orientación marco 3.5 en lugar de 2.0, pero todavía tenía el mismo problema (tal vez no lo hice este derecho).

Alguien tiene alguna sugerencia?

Un par de cosas que me pueden ayudar:

  • ¿Hay algún otro tipo de asignaciones de memoria que no estoy de rastreo?
  • ¿Cómo es que las cifras no cuadran? Tengo 5 MB de uso de la memoria CRT, 1,5 MB de memoria de .NET así que ¿cómo es que toda la aplicación utiliza bytes privados 30MB? Es que todos atado en el marco .NET? ¿Por qué no veo esto en la herramienta de fugas? No será el marco .NET aparecer como una especie de memoria asignada?
  • Cualquier otras herramientas de detección de fugas que funcionan bien con las aplicaciones de modo mixto?

Gracias por cualquier ayuda

John

¿Fue útil?

Solución

Aceptar finalmente encontré el problema.

Fue causado por una configuración incorrecta para / EH (Control de excepciones).

Básicamente, con aplicaciones .NET modo mixto, es necesario asegurarse de que todas las bibliotecas enlazadas estáticamente son recopilados con / EHa en lugar del predeterminado / EHS.

(La propia aplicación también se debe compilar con / EHa, pero esto es un hecho -.. El compilador informará de error si no lo usa El problema es cuando se vincula en otras librerías nativas estáticas)

El problema es que las excepciones atrapados en el bit gestionado de la aplicación, que fueron arrojados dentro de las bibliotecas nativas compilados con / EHS terminan por no controlar la excepción correctamente. Los destructores de objetos C ++ no son entonces llamados correctamente.

En mi caso, esto sólo ocurrió en un lugar raro, por lo tanto, por qué me tomó las edades de detectar.

Otros consejos

Al igual que Spence estaba diciendo, pero para C ++ / CLI;) ....

Para cualquier objeto que se está utilizando en C ++ / CLI, si crea más de ese objeto a partir de código que C ++, usted debe tratar de utilizar seymantics asignación de pila, a pesar de que esto es una especie de magia compilador de cosas, es capaz de configurar el __try anidada {} {} __finally declaraciones que se pueden utilizar para el uso de código nativo (que es la configuración de una forma de no perder una llamada a disponer).

de Nish artículo en el proyecto de código aquí en C ++ / CLI semántica de asignación de pila es bastante bueno y entra en profundidad acerca de cómo emular el uso de {}.

También debe asegurarse de eliminar cualquier objeto que implment IDisposable como no se puede llamar a Dispose en C ++ / CLI, eliminar lo hace por usted, si no el uso de la semántica de la pila ..

Por lo general llamada cercana a mí mismo en arroyos y tratar de asignar nullptr cuando he terminado con el objeto de, por si acaso.

También es posible que desee comprobar hacia fuera este artículo sobre problemas de memoria , perticularly sobre suscriptores de eventos, si está asignando el evento de que sus objetos, es posible que haya un escape ...

Como último recurso (o tal vez primero :), una cosa que he hecho en el pasado es hacer uso de la API de perfiles de CLR, aquí hay otro artículo sobre cómo hacer esto, escritor del autor (Jay Hilyard) tiene un ejemplo que respuestas;

  • de cada tipo .NET que se utiliza, cómo muchas instancias de objetos están siendo ¿asignado?
  • ¿De qué tamaño son las instancias de cada tipo?
  • ¿Qué notificaciones proporciona el GC, ya que va a través de una recolección de basura y lo ¿Puedes averiguar?
  • Cuando se hace el GC recoger las instancias de objeto?

En caso de obtener una idea mejor que algunos de perfiles de productos básicos, me he dado cuenta de que pueden ser en ocasiones engañosa dependiendo de su porofile asignación (por cierto. Cuidado con los grandes temas objeto del montón,> ~ 83KB objetos están especialmente manipulados, en ese caso, yo lo recomendaría, para salir del montón de objetos grandes:.)

Teniendo en cuenta sus comentarios, algunas cosas más ...

He publicado antes sobre la carga de la imagen no está cargando cuota o cualquier otra estadística disernable, lo que esto significa, es posible que necesite para localizar a algún problema de mango o cargador (consulte Bloqueo de cargador con el tiempo), pero antes de eso, se puede intentar establecer un poco Regiones de ejecución restringidos , pueden trabajar maravillas, sino que también son por desgracia difícil de retro-fit en código no puro.

Esta reciente MSDN Mag , documento Artículo es un montón de Monitor de rendimiento sperlunking memoria de tipo (seguimiento para este más viejo ).

En la VS Perf Blog , que muestran cómo utilizar SOS en visual Studio, que puede ser útil, para localizar a rouge DLL, los mensajes relacionados también son buenos.

Blog de Maoni Esteban y empresa , es decir que está en el equipo de Potencia, pero esencialmente el 100% de sus mensajes son con respecto al GC hasta el punto de que puede, por así escribió de a él.

Rick Byers es un desarrollador con el equipo de diagnóstico CLR, muchos de su blog -buddies son tambiénbuena de fuente, sin embargo, me gustaría sugerir fuertemente también refiriéndose a la nueva dev / diagnóstico foro . Recientemente han ampliado el alcance de sus discusiones.

herramientas de cobertura de código y trazado a menudo puede ayudar, para darle una visión general de lo que está actualmente en funcionamiento.

(specically, los stat perticular de puede no ser que le da una visión global de lo que se plauging su código, puedo decir que, recientemente, he encontrado (incluso con los binarios .net4beta, el perfilador de esta empresa , es bastante bueno, es capaz de derivar de nativos / fugas gestionadas desde su perfil trazas, que trae de nuevo a las líneas de fuente exacta (aunque optimizado, bastante bien (y que tiene un juicio 30 días)))).

Buena suerte !! La esperanza alguna de esta ayuda, es sólo fresco en mi mente, como lo estoy haciendo gran parte de la misma obra en este momento;)

Pruebe: DebugDiags .
Después de generar algunos volcados de memoria, que le dará un buen veraniega de lo que la memoria se ha asignado, y en función de la búsqueda de sus de AP, se le puede decir por quién fue asignado.

Es posible que tenga una fuga de referencia, mira en HORMIGAS software de perfiles. Ants Profiler

Una fuga de referencia es el .NET equivalente a una pérdida de memoria, se mantiene referencias a un objeto que para que se recoge la basura, y por lo tanto que la memoria en uso comienza a subir.

¿Es posible que han pasado varias trituradores, que puede suceder si el uso de GDI + y muchas otras API.

Si su ejecutar la herramienta de análisis estático FXCop que tiene una regla para comprobar si usted ha llamado dispose (o utilizó los "usando") declaraciones sobre los objetos que proporcionan la interfaz. En .Net si una función utiliza el código no administrado por lo general proporcionar un método dispose o cerca para que se escape el recurso / memoria.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top