Trabajando con Heap Corruptions in .NET

Warning: array_merge(): Argument #2 is not an array in D:\home\site\wwwroot\wp-content\plugins\simple-social-share\simple-social-share.php on line 144

Una de las mejores características de .NET Framework es la administración automática de la memoria, eso significa que no tenemos que estar pendientes de memory leaks, corrupciones y demás problemas. Pero en este artículo encontraremos que esto no es así todas las veces. Os quiero mostrar un bug que he encontrado en una aplicación .NET 4.

Como ya sabreis el clr tiene una heap administrado que contiene todos los objetos que se han ido creando en todo el código ejecutado, y es precisamente en ese managed heap donde el recolector de basura trabaja para ordenarlo y limpiarlo. Vamos a utilizar algunos comandos de WinDBG para ver el estado del heap

Durante la ejecución de mi aplicación aleatoriamente la aplicación me lanza un System.ExecutionEngineException. Como se puede imaginar esta excepción es fatal y no hay oportunidad para cachearla así que mi aplicación se cierra cuando se encuentra con una excepción como esta.

 

Como vemos en esta salida de WinDBG tenemos varios thread y en el thread 44 hay una excepción (GC) (Threadpool Worker) System.ExecutionEngineException (0000000002871228) y esta dirección es la dirección de memoria donde es el System.ExecutionEngineException. Empecemos la investigación desde ahí.

 

 

Ahora como siempre examinemos las pilas nativas y administrada.

En mi pila administrada mi último frame es System.Text.StringBuilder.ToString(), así que asumimos que estamos creando memoria para ese string. Si miramos a la pila nativa observamos que justo en ese punto se estaba haciendo una recolección de basura.

La secuencia es: FramedAllocateString -> GCHeap::Alloc -> gc_heap::try_allocate_more_space -> GCHeap::GarbageCollectGeneration -> gc_heap::garbage_collect -> :gc_heap::gc1

Este punto estamos seguros de que realmente se estaba reservando memoria para ese string, pero como no habría más memoria disponible se había lanzado una recolección de basura y ahí es donde el runtime encontró la corrupción del heap.

Hay un commando muy util en WinDBG !verifyheap que nos permite comprobar que hay signos de corrupción en el heap adminsitrado.

 

El commando !verifyheap nos está diciendo que en ese preciso momento se estaba realizando una recolección de basura que las estructuras del gc puede que no estén en un estado válido para que este comando extraiga toda la información, pero al final del reporte encontramos que hay un objeto que tiene un miembro inválido, este objeto es un System.IO.StreamReader y el miembro invalido es System.Char[] 0000000008f1b750 charBuffer.

¿Qué podemos hacer con este problema?

Teniendo en cuenta que es un problema de corrupción en la pila lo que tenemos que hacer es simplemente llamar al servicio de soporte de Microsoft y notificarle lo que hemos encontrado.

Happy debugging. Luis.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *