2009-08-22 10 views
8

Estoy tratando de encontrar una manera de anular globalmente funciones malloc y relacionadas en Visual C++ (2005). Mi configuración es una DLL con biblioteca de tiempo de ejecución estáticamente vinculada que consiste en mi propio código de C++, C++ externo y código c. Lo que quiero lograr es permitir que un usuario del dll establezca sus propias implementaciones de las funciones de asignación de memoria.Anular globalmente malloc en visual C++

Soluciones que no puedo utilizar:

  • Anulación de nuevo y eliminar a nivel mundial, hay un montón de librerías externas en C mi base de código que significa esto no va a captura de muchas asignaciones.
  • que define malloc en un símbolo diferente. Esto me obligaría a llevar esta definición a la configuración de compilación de todas las bibliotecas externas utilizadas y realmente quiero evitar esto.

Cosas que no me importan

  • Si cualquiera de las bibliotecas externas están asignando memoria de alguna otra manera (HeapAlloc, archivos de memoria asignada o lo que sea que llegar a), acepto que esto no se rastreará correctamente anulando malloc.

La solución más razonable que puedo llegar a es de alguna manera interferir con el proceso de enlace y asegurarse de que mi propia malloc está siendo vinculado en lugar de los estándar, preferiblemente Me gustaría ser capaz de utilizar el viejo malloc funciona como predeterminado

En google perf-tools parece que parchean el código de las funciones manualmente en tiempo de ejecución para permitir que se llame a una función de enlace antes de llamar a la función original. ¿Es esta la mejor manera de hacer esto?

+0

¿Está intentando hacer lo mismo que LD_PRELOAD en Linux? – LB40

+0

No estoy tan familiarizado con LD_PRELOAD, pero parece estar relacionado con la vinculación dinámica, en mi caso malloc, libre y sus amigos están vinculados estáticamente. – Laserallan

+0

¿Podría explicar por qué cree que necesita hacer esto? –

Respuesta

2

Puede usar Detours de Microsoft (pagar por comercial) o volver a escribir las tablas de importación para los dlls que usa.

+0

Esto definitivamente podría funcionar si utilicé la biblioteca de tiempo de ejecución vinculada dinámicamente. Sin embargo, me preocupa que anule las funciones para el ejecutable usando mi biblioteca también. – Laserallan

+0

Sí, lo harías. Es una cosa de todo el proceso. –

5

Lo siguiente es cierto en Linux, pero también puede aplicarse al C++ visual de Win.

  1. Malloc funciton es provista por la librería del sistema glibc. El ejecutable está vinculado de manera predeterminada contra él.

  2. Cuando se ejecuta el programa, el cargador dinámico advierte que el ejecutable necesita la función malloc y busca la primera biblioteca que lo proporciona.

  3. Como glibc es (por defecto) el último en esa lista, la biblioteca encontrada puede no ser glibc.

A menos que haya vinculado estáticamente glibc en el ejecutable, la solución obvia es vincular el ejecutable con la librería que proporciona su propia malloc, y asegúrese de que lo hace anular uno del sistema.

+0

esta es la respuesta correcta – pgast

+1

No funciona de esa manera en Windows. Las importaciones no son solo por nombre. Las importaciones se enumeran por DLL que debe proporcionarlo. El formato PE le permite importar el mismo nombre de función de dos DLL. – MSalters

+0

Genial, entonces es un poco _superior_ que en Linux - puedes asignar directamente la función a una biblioteca, de modo que un malloc definido por el usuario será cargado desde una biblioteca específica. Eso es lo que queremos, ¿no? –

1

Lamentablemente no sé lo suficiente sobre el enlazador de microsoft. Pero ld tiene '--wrap' que puedes usar para algo como malloc o libre o cualquier otra cosa (hago esto).

todas las llamadas a malloc serán redirigidas a una función llamada __wrap_malloc que usted ha implementado, puede llamar real malloc con __real_malloc.Esto tiene el beneficio de capturar cualquier mallocs usado en bibliotecas externas también. Estoy seguro de que el enlazador de Microsoft podría tener una función similar.

+0

No encontré nada de eso en el enlazador de Visual Studio y lo más parecido que encontré es usando la herramienta lib.exe (http://msdn.microsoft.com/en-us/library/7ykb2k5f(VS.71). aspx). Puede extraer y agregar archivos .obj a una biblioteca estática. Técnicamente, podría crear mi propia versión del archivo .lib de la biblioteca estándar con funciones malloc/calloc/free/realloc parcheadas. Si acabo de encontrar una herramienta que pueda cambiar el nombre de las funciones dentro de un archivo .obj, sería posible cambiar el nombre de las versiones anteriores y asegurarme de que mis funciones de anulación las llamen. – Laserallan

1

Puede eliminar esos archivos .obj con lib.exe de lib. No puedo ser más específico, pero recuerdo haberlo hecho cuando estaba construyendo Chromium desde la fuente.

+0

¿No está sugiriendo manipular la biblioteca incorporada de tiempo de ejecución de Microsoft C++? – rustyx

5

Tengo muchas ganas de encontrar una buena solución para esto también. Compilamos para múltiples plataformas, por lo tanto, en el lado de las cosas que no son de Windows que podemos usar: envolvernos felizmente. Solo tenemos que crear las funciones de reemplazo y todo funciona sin errores ni hacks.

Por el lado de las ventanas, anulamos las llamadas malloc, pero luego usamos /FORCE:MULTIPLE para tratar los errores del enlazador. Funciona, se llaman las funciones de memoria y todo se rastrea, pero se siente como un hack.

De MSDN:

A file created with this option may not run as expected. The linker will not link incrementally when the /FORCE option is specified.

No sólo se siente como un corte, que mata a Editar y continuar en el proceso.

La opción /FORCE:MULTIPLE puede solucionar sus problemas, pero no lo estoy sugiriendo como una cura, todavía estoy tratando de encontrarlo.

MSDN /FORCE Documentation

: D

+0

Esto parece útil. ¿Qué orden de resolución se usa? ¿Siempre mi propio malloc es el que se usa cuando hay un conflicto con la biblioteca estándar? ¿Enrutas las llamadas a través de tu malloc personalizado a la definición original o arrojaste por completo la versión de biblioteca estándar de malloc? – Laserallan

+0

Estamos usando dlmalloc para hacer las asignaciones reales. Tengo la impresión de que siempre tomará las funciones anuladas, pero ahora que has planteado la pregunta, no estoy seguro. : D –

1

quitar todos los archivos .obj que contienen las funciones de gestión de memoria de las bibliotecas de tiempo de ejecución utilizando la herramienta LIB, a continuación, utilizar la opción "Omitir bibliotecas predeterminadas" en el IDE y de forma manual especifique "su" biblioteca de tiempo de ejecución en su lugar. Luego compila; Debería obtener algunos errores de vinculador sobre malloc indefinido y free y así sucesivamente. ¡Aquí es donde tu entras!

(Es posible que también quieren hacer algo similar a la de C++ bibliotecas si se utilizan, aunque creo que la operator new s llamada malloc por defecto por lo que podría ser bueno para ir de inmediato.)

El Visual La instalación de Studio viene con el código fuente de tiempo de ejecución (mira en vc/crt/src en tu carpeta de instalación de Visual Studio), por lo que encontrar el conjunto completo de funciones de administración de memoria es bastante sencillo. No tengo los detalles exactos a mano (el empleador anterior ...) pero, según recuerdo, solo me llevó alrededor de medio día resolverlos a pesar de que había más funciones de asignación de memoria de lo que esperaba.

+0

Gracias, esto parece agregar la última pieza del rompecabezas. – Laserallan

2

Una solución que he usado es reconstruir la biblioteca de tiempo de ejecución C (Crt) de Visual C++ desde el código fuente.

Se puede encontrar aquí en esta carpeta:

C: \ Archivos de programa \ Microsoft Visual Studio 9.0 \ VC \ CRT

Asegúrese de que inicie el símbolo del comando de Visual Studio para construirlo. Ejecutar nmake es suficiente para comenzar a construir, aunque es posible que desee averiguar qué objetivo construir y esto significa que tendrá que entender el archivo MAKE.

Se puede tomar un esfuerzo por entender cómo construir el CRT, pero una vez que lo tienes construcción puede añadir su propio código en malloc, libre y realloc, etc.

Por desgracia he oído un rumor de que nos no podrá construir el crt desde el código fuente comenzando con Visual Studio 2010.