Valgrind
Valgrind () es una herramienta de programación para depuración de memoria, detección de pérdidas de memoria y creación de perfiles.
Valgrind se diseñó originalmente para ser una herramienta de depuración de memoria con licencia gratuita para Linux en x86, pero desde entonces ha evolucionado hasta convertirse en un marco genérico para crear herramientas de análisis dinámico, como verificadores y perfiladores.
Descripción general
Valgrind es, en esencia, una máquina virtual que utiliza técnicas de compilación justo a tiempo, incluida la recompilación dinámica. Nada del programa original se ejecuta nunca directamente en el procesador host. En cambio, Valgrind primero traduce el programa a una forma temporal y más simple llamada representación intermedia (IR), que es una forma de asignación única estática, neutral al procesador y basada en un formulario. Después de la conversión, una herramienta (ver más abajo) es libre de realizar cualquier transformación que desee en el IR, antes de que Valgrind traduzca el IR nuevamente a código de máquina y permita que el procesador host lo ejecute. Valgrind recompila código binario para ejecutarlo en CPU host y de destino (o simuladas) de la misma arquitectura. También incluye un código auxiliar de GDB para permitir la depuración del programa de destino mientras se ejecuta en Valgrind, con "comandos de monitoreo" que permiten consultar la herramienta Valgrind para obtener información diversa.
Se pierde una cantidad considerable de rendimiento en estas transformaciones (y generalmente, el código que inserta la herramienta); Por lo general, el código se ejecuta con Valgrind y el comando "ninguno" La herramienta (que no le hace nada al IR) se ejecuta entre un 20% y un 25% de la velocidad del programa normal.
Herramientas
Comprobación de memoria
Hay varias herramientas incluidas con Valgrind (y varias externas). La herramienta predeterminada (y la más utilizada) es Memcheck. Memcheck inserta código de instrumentación adicional alrededor de casi todas las instrucciones, lo que realiza un seguimiento de la validez (toda la memoria no asignada comienza como no válida o "indefinida"), hasta que se inicializa en un estado determinista, posiblemente de otra memoria) y direccionabilidad (si la dirección de memoria en cuestión apunta a un bloque de memoria asignado, no liberado), almacenado en los llamados bits V y Un poco respectivamente. A medida que los datos se mueven o manipulan, el código de instrumentación realiza un seguimiento de los bits A y V, por lo que siempre son correctos en un nivel de un solo bit.
Además, Memcheck reemplaza el asignador de memoria C estándar con su propia implementación, que también incluye protectores de memoria alrededor de todos los bloques asignados (con los bits A establecidos en "no válidos"). Esta característica permite a Memcheck detectar errores uno por uno cuando un programa lee o escribe fuera de un bloque asignado por una pequeña cantidad. Los problemas que Memcheck puede detectar y advertir incluyen los siguientes:
- Uso de la memoria no inicializada
- Memoria de lectura/escritura después de haber sido
free
'd - Lectura/escritura fuera del final
malloc
bloques - Residuos de memoria
El precio de esto es la pérdida de rendimiento. Los programas que se ejecutan bajo Memcheck generalmente se ejecutan entre 20 y 30 veces más lento que los que se ejecutan fuera de Valgrind y usan más memoria (hay una penalización de memoria por asignación). Por lo tanto, pocos desarrolladores ejecutan su código en Memcheck (o cualquier otra herramienta Valgrind) todo el tiempo. Lo más común es que utilicen este tipo de herramientas para rastrear algún error específico o para verificar que no hay errores latentes (del tipo que Memcheck puede detectar) en el código.
Otras herramientas
Además de Memcheck, Valgrind tiene varias otras herramientas:
- Ninguno, ejecuta el código en la máquina virtual sin realizar ningún análisis y por lo tanto tiene la CPU más pequeña posible y la memoria de todas las herramientas. Desde Valgrind mismo proporciona un rastro de una falla de segmentación, el ninguno herramienta proporciona este trazaback a la sobrecarga mínima.
- Addrcheck, similar a Memcheck pero con mucho más pequeño CPU y memoria sobrecabezada, capturando así menos tipos de errores. Addrcheck ha sido eliminado a partir de la versión 3.2.0.
- MassifUn perfilador. El multivisualizador GUI separado visualiza la salida de Massif.
- Helgrind y DRD, detectar las condiciones de carrera en código multiteleado
- CachegrindUn perfilador de caché. El GUI KCacheGrind separado visualiza la salida de Cachegrind.
- Callgrind, un analizador de gráficos de llamada creado por Josef Weidendorfer, añadido a Valgrind a la versión 3.2.0. KCacheGrind puede visualizar la salida de Callgrind.
- DHAT, herramienta de análisis de montones dinámicos que analiza cuánto memoria se asigna y por cuánto tiempo, así como patrones de uso de memoria.
- exp-bbv, un simulador de rendimiento que extrapola el rendimiento de un pequeño conjunto de muestras.
exp-sgcheck (llamado exp-ptrcheck antes de la versión 3.7) se eliminó en la versión 3.16.0. Era una herramienta experimental para encontrar errores de desbordamiento de matriz global y de pila, que Memcheck no puede encontrar.
También hay varias herramientas desarrolladas externamente disponibles. Una de esas herramientas es ThreadSanitizer, otro detector de condiciones de carrera.
Plataformas compatibles
A partir de la versión 3.4.0, Valgrind es compatible con Linux en x86, x86-64 y PowerPC. En la versión 3.6.0 se agregó soporte para Linux en ARMv7 (usado, por ejemplo, en ciertos teléfonos inteligentes). Se agregó soporte para Solaris en la versión 3.11.0. Se agregó compatibilidad con OS X en la versión 3.5.0. Se agregó soporte para FreeBSD x86 y amd64 en la versión 3.18.0. Existen puertos no oficiales para otras plataformas similares a Unix (como OpenBSD y NetBSD). A partir de la versión 3.7.0 se agregó soporte para la plataforma ARM/Android.
Desde la versión 3.9.0 hay soporte para Linux en MIPS64 little y big endian, para MIPS DSP ASE en MIPS32, para instrucciones de coma flotante decimal s390x, para instrucciones POWER8 (Power ISA 2.07), para instrucciones Intel AVX2, para Intel Extensiones de sincronización transaccional, tanto RTM como HLE y soporte inicial para memoria transaccional de hardware en POWER.
Historia y desarrollo
El nombre Valgrind es una referencia a la entrada principal del Valhalla de la mitología nórdica. Durante el desarrollo (antes del lanzamiento), el proyecto se llamó Heimdall; sin embargo, el nombre habría entrado en conflicto con un paquete de seguridad.
El autor original de Valgrind es Julian Seward, quien en 2006 ganó un premio Google-O'Reilly Open Source por su trabajo en Valgrind.
Varios otros también han hecho contribuciones significativas, incluidos Nicholas Nethercote, Bart Van Assche, Florian Krohm, Tom Hughes, Philippe Waroquiers, Mark Wielaard, Paul Floyd, Petar Jovanovic, Carl Love, Cerion Armour-Brown e Ivo Raisr.
Es utilizado por varios proyectos basados en Linux.
Limitaciones de Memcheck
Además de la penalización en el rendimiento, una limitación importante de Memcheck es su incapacidad para detectar todos los casos de errores de límites en el uso de datos estáticos o asignados en pila. El siguiente código pasará la herramienta Memcheck en Valgrind sin incidentes, a pesar de contener los errores descritos en los comentarios:
int Estática[5]; int func()vacío) {} int Stack[5]; Estática[5] = 0; /* Error - Static[0] a Static[4] existen, Static[5] está fuera de límites */ Stack [5] = 0; /* Error - Stack[0] a Stack[4] existen, Stack[5] está fuera de límites */ retorno 0; }
La incapacidad de detectar todos los errores relacionados con el acceso a los datos asignados a la pila es especialmente notable ya que Ciertos tipos de errores de pila hacen que el software sea vulnerable al clásico. Explotación de destrucción de pilas.