Pregunta

Esto es un poco hipotético y muy simplificado pero...

Supongamos un programa que llamará funciones escritas por terceros.Se puede suponer que estas partes no son hostiles, pero no se puede suponer que sean "competentes".Cada función tomará algunos argumentos, tendrá efectos secundarios y devolverá un valor.No tienen estado mientras no están corriendo.

El objetivo es garantizar que no puedan causar pérdidas de memoria registrando todos los mallocs (y similares) y luego liberando todo después de que salga la función.

es posible?¿Es esto práctico?

PD.La parte importante para mí es asegurarme de que no persistan las asignaciones, por lo que las formas de eliminar las pérdidas de memoria sin hacerlo no me resultan útiles.

¿Fue útil?

Solución

No especifica el sistema operativo o el entorno, esta respuesta asume Linux, glibc y C.

Puede configurar __malloc_hook, __free_hook y __realloc_hook para que apunten a funciones que se llamarán desde malloc(), realloc() y free() respectivamente.Hay una página de manual __malloc_hook que muestra los prototipos.Puede agregar asignaciones de pistas en estos enlaces y luego regresar para permitir que glibc maneje la asignación/desasignación de memoria.

Parece que desea liberar las asignaciones en vivo cuando regrese la función de terceros.Hay formas de hacer que gcc inserte llamadas automáticamente en cada entrada y salida de función usando -finstrument-functions, pero creo que eso sería poco elegante para lo que estás tratando de hacer.¿Puede hacer que su propio código llame a una función en su biblioteca de seguimiento de memoria después de llamar a una de estas funciones de terceros?Luego puede verificar si hay asignaciones que la función de terceros aún no haya liberado.

Otros consejos

Primero, debe proporcionar los puntos de entrada para malloc() y free() y amigos.Debido a que este código ya está compilado (¿verdad?), no puedes depender de él #define para redirigir.

Luego puede implementarlos de la manera obvia y registrar que provienen de un determinado módulo vinculando esas rutinas a esos módulos.

La forma más rápida implica sin registro alguno. Si la cantidad de memoria que utilizan está limitada, ¿por qué no preasignar todo el "montón" que necesitarán y escribir un asignador a partir de eso?Luego, cuando haya terminado, libere todo el "montón" y ¡listo!Podrías extender esta idea a varios montones si es más complejo que eso.

Si realmente necesita "iniciar sesión" y no crear su propio asignador, aquí tiene algunas ideas.Uno, use una tabla hash con punteros y encadenamiento interno.Otra sería asignar espacio adicional delante de cada bloque y colocar allí su propia estructura que contenga, por ejemplo, un índice en su "tabla de registro", luego mantener una lista libre de entradas de la tabla de registro (como una pila, para obtener una libre). o devolver uno gratis es O(1)).Esto requiere más memoria pero debería ser rápido.

¿Es práctico?Creo que lo es, siempre y cuando la velocidad sea aceptable.

Puede ejecutar las funciones de terceros en un proceso separado y cerrar el proceso cuando haya terminado de usar la biblioteca.

Una mejor solución que intentar registrar mallocs podría ser aislar las funciones cuando las llama: darles acceso a un segmento fijo de memoria y luego liberar ese segmento cuando la función termine de ejecutarse.

El uso ilimitado e incompetente de la memoria puede ser tan dañino como el código malicioso.

¿No puedes simplemente obligarlos a asignar toda su memoria en la pila?De esta manera, se garantizará su liberación después de que finalice la función.

En el pasado escribí una biblioteca de software en C que tenía un subsistema de administración de memoria que contenía la capacidad de registrar asignaciones y liberaciones, y de hacer coincidir manualmente cada asignación y liberación.Esto fue de cierta utilidad al intentar encontrar pérdidas de memoria, pero su uso era difícil y consumía mucho tiempo.La cantidad de registros era abrumadora y tomó mucho tiempo comprenderlos.

Dicho esto, si su biblioteca de terceros tiene asignaciones extensas, lo más probable es que no sea práctico realizar un seguimiento mediante el registro.Si está ejecutando en un entorno Windows, le sugeriría utilizar una herramienta como Purify[1] o BoundsChecker[2] que debería poder detectar fugas en sus bibliotecas de terceros.La inversión en la herramienta debería amortizarse con el tiempo ahorrado.

[1]: http://www-01.ibm.com/software/awdtools/purify/ Purificar

[2]: http://www.compuware.com/products/devpartner/visualc.htm Comprobador de límites

Como te preocupan las pérdidas de memoria y hablas de malloc/free, supongo que estás en C.También supongo, según su pregunta, que no tiene acceso al código fuente de la biblioteca de terceros.

Lo único que se me ocurre es examinar el consumo de memoria de su aplicación antes y después de la llamada, registrar los mensajes de error si son diferentes y convencer al proveedor externo para que solucione cualquier fuga que encuentre.

Si tiene dinero de sobra, considere usar Purify para realizar un seguimiento de los problemas.Funciona de maravilla y no requiere código fuente ni recompilación.También hay otras bibliotecas malloc de depuración disponibles que son más económicas.Electric Fence es un nombre que recuerdo.Dicho esto, los ganchos de depuración mencionados por Denton Gentry también parecen interesantes.

Si eres demasiado pobre para Purify, prueba Valgrind.Es mucho mejor que hace 6 años y es mucho más fácil sumergirse en él que Purify.

Microsoft Windows proporciona (use SUA si necesita un POSIX), muy posiblemente, la infraestructura de montón + (otra API conocida por usar el montón) más avanzada de cualquier sistema operativo disponible en la actualidad.

los ganchos de depuración __malloc() y las interfaces de depuración CRT asociadas son útiles para los casos en los que se tiene el código fuente para las pruebas; sin embargo, a menudo pueden omitir asignaciones de bibliotecas estándar u otro código vinculado.Esto es lo esperado ya que son la infraestructura de depuración del montón de Visual Studio.

banderas es un conjunto muy completo y detallado de capacidades de depuración que se ha incluido con Windows durante muchos años.Tener funcionalidad avanzada para casos de uso de código fuente y binario únicamente (como lo es la infraestructura de depuración del montón del sistema operativo).

Puede registrar seguimientos de pila completos (repaginando información simbólica en una operación posterior al proceso), de todos los usuarios del montón, para todos los puntos de entrada de modificación del montón, en serie si es necesario.Además, puede modificar el montón con casos patológicos que pueden alinear la asignación de datos de modo que la protección de página ofrecida por el sistema VM se asigne de manera óptima (es decir,asigne el bloque de montón solicitado al final de una página, de modo que incluso se detecte un desbordamiento de un solo byte en el momento del desbordamiento.

umdh es una herramienta que puede ayudar a evaluar el estado en varios puntos de control; sin embargo, los datos se acumulan continuamente durante la ejecución del objetivo o no es una simple parada de depuración de puntos de control en el contexto tradicional.También, ADVERTENCIA, La última vez que verifiqué, al menos, el tamaño total del búfer circular que almacena la información de la pila, para cada solicitud, es algo pequeño (entradas de 64k (entradas+pila)), por lo que es posible que deba realizar un volcado rápido para los usuarios de mucho montón.Hay otras formas de acceder a estos datos, pero umdh es bastante sencillo.

NOTA hay 2 modos;

  1. MODO 1, umdh {-p:ID-Proceso|-pn:NombreProceso} [-f:NombreArchivo] [-g]
  2. MODO 2, umdh [-d] {Archivo1} [Archivo2] [-f:Nombre de archivo]

    No sé qué locura se apoderó del desarrollador que eligió alternar entre el especificador de argumentos -p:foo y el orden simple de los argumentos, pero puede resultar un poco confuso.

El SDK de depuración funciona con otras herramientas, memsnap es una herramienta que aparentemente se centra en la pérdida de memoria y demás, pero no la he usado, su kilometraje puede variar.

Ejecute gflags sin argumentos para el modo UI, +arg's y /args son diferente "modos" de uso también.

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