Reemplazo de malloc de Windows(por ejemplo, tcmalloc) y enlace de crt dinámico
dll msvcrt (4)
Un programa C ++ que utiliza varias DLL y QT debe estar equipado con un reemplazo de malloc (como tcmalloc ) para problemas de rendimiento que se puede verificar que sean causados por malloc de Windows. Con Linux, no hay problema, pero con Windows, hay varios enfoques, y ninguno de ellos me resulta atractivo:
1. Coloque new malloc en lib y asegúrese de vincularlo primero (Other SO-question)
Esto tiene la desventaja de que, por ejemplo, strdup seguirá utilizando el antiguo malloc y un programa gratuito puede bloquear el programa .
2. Elimine malloc de la biblioteca libcrt estática con lib.exe (Chrome)
Esto se prueba / usa (?) Para chrome/chromium , pero tiene la desventaja de que solo funciona con enlaces estáticos del crt. El enlace estático tiene el problema si una biblioteca del sistema está vinculada dinámicamente contra msvcrt, puede haber discrepancias en la asignación / desasignación del montón . Si lo entiendo correctamente, tcmalloc podría vincularse dinámicamente de modo que haya un montón común para todos los dlls autocompilados (lo cual es bueno).
3. Patch crt-source code (firefox)
El jemalloc de Firefox aparentemente parchea el código fuente de CRT de Windows y crea un nuevo crt. Esto tiene nuevamente el problema de vinculación estático / dinámico anterior.
Uno podría pensar en usar esto para generar un MSVCRT dinámico, pero creo que esto no es posible, porque la licencia prohíbe proporcionar un MSVCRT parcheado con el mismo nombre.
4. Parcheo dinámico de CRT cargado en tiempo de ejecución
Algunos asignadores de memoria comercial pueden hacer tal magia. tcmalloc también puede hacerlo, pero parece bastante feo. Tenía algunos problemas, pero se han solucionado. Actualmente, con tcmalloc no funciona en ventanas de 64 bits.
¿Hay mejores enfoques? ¿Algún comentario?
¿De dónde viene su premisa "Un programa en C ++ que usa varias DLL y QT debería estar equipado con un reemplazo de malloc"?
En Windows, si todos los dlls usan el MSVCRT compartido, entonces no hay necesidad de reemplazar malloc. Por defecto, Qt compila contra el dll de MSVCRT compartido.
Uno tendrá problemas si:
1) mezclar dlls que usan enlaces estáticos vs usar el VCRT compartido
2) Y también memoria libre que no fue asignada de dónde vino (es decir, memoria libre en un DLL estáticamente vinculado que fue asignado por el VCRT compartido o viceversa).
Tenga en cuenta que agregar su propio contenedor contado en torno a un recurso puede ayudar a mitigar los problemas asociados con los recursos que se deben desasignar de maneras particulares (es decir, un contenedor que dispone de un tipo de recurso mediante una devolución al dll de origen, un diferente contenedor para un recurso que se origina en otro archivo DLL, etc.).
Es un atrevido reclamo que un programa C ++ "debería estar equipado con un reemplazo malloc (como tcmalloc) para problemas de rendimiento ..."
"[En] 6 de 8 puntos de referencia populares ... [aplicaciones de tamaño real] reemplazando el asignador personalizado, en el que las personas habían invertido cantidades significativas de tiempo y dinero, ... con el asignador mudo provisto por el sistema [cedió] mejor rendimiento. ... Los asignadores personalizados más simples, ajustados para situaciones muy especiales, son los únicos que pueden proporcionar ganancias ". - Andrei Alexandrescu
La mayoría de los asignadores de sistemas son tan buenos como un asignador de propósito general . Puede hacerlo mejor solo si tiene un patrón de asignación muy específico.
Típicamente, tales patrones especiales se aplican solo a una parte del programa, en cuyo caso, es mejor aplicar el asignador personalizado a la parte específica que puede beneficiarse de lo que es reemplazar globalmente el asignador.
C ++ proporciona algunas formas de reemplazar selectivamente el asignador. Por ejemplo, puede proporcionar un asignador a un contenedor STL o puede anular nuevo y eliminar clase por clase. Ambos le dan mucho mejor control que cualquier hack que reemplace globalmente el asignador.
Tenga en cuenta también que reemplazar malloc y free will no necesariamente cambiará el asignador utilizado por los operadores new y delete. Si bien el nuevo operador global se implementa típicamente utilizando malloc, no es necesario que lo haga. Entonces, reemplazar Malloc puede no afectar la mayoría de las asignaciones.
Si está utilizando C, es probable que pueda envolver o reemplazar llamadas malloc y llamadas gratuitas con su asignador personalizado justo donde sea importante y dejar el resto del programa para usar el asignador predeterminado. (Si ese no es el caso, es posible que desee considerar algunas refactorizaciones).
Los asignadores del sistema tienen décadas de desarrollo detrás de ellos. Son estables y bien probados. Funcionan extremadamente bien para casos generales (en términos de velocidad bruta, contención de hilos y fragmentación). Tienen versiones de depuración para detección de fugas y soporte para herramientas de seguimiento. Algunos incluso mejoran la seguridad de su aplicación al proporcionar defensas contra las vulnerabilidades de desbordamiento del búfer de pila. Lo más probable es que las bibliotecas que desea utilizar hayan sido probadas solo con el asignador del sistema.
La mayoría de las técnicas para reemplazar el asignador del sistema pierden estos beneficios. En algunos casos, incluso pueden aumentar la demanda de memoria (porque no se pueden compartir con el tiempo de ejecución de DLL posiblemente utilizado por otros procesos). También tienden a ser extremadamente frágiles frente a los cambios en la versión del compilador, la versión en tiempo de ejecución e incluso la versión del sistema operativo. El uso de una versión ajustada del tiempo de ejecución evita que los usuarios obtengan los beneficios de las actualizaciones en tiempo de ejecución del proveedor del sistema operativo. ¿Por qué renunciar a todo eso cuando puede retener esos beneficios aplicando un asignador personalizado solo a la parte excepcional del programa que puede beneficiarse de ello?
P: Un programa de C ++ que se divide en varios dlls debería:
A) reemplazar malloc?
B) asegurar que la asignación y la desasignación ocurra en el mismo módulo dll?
R: La respuesta correcta es B. Un diseño de aplicación c ++ que incorpora DLL múltiples DEBE garantizar que exista un mecanismo para garantizar que las cosas que están asignadas en el montón en una DLL, estén libres por el mismo módulo dll.
¿Por qué dividirías un programa de C ++ en varios dlls de todos modos? Por programa c ++ me refiero a que los objetos y tipos con los que se trata son plantillas C ++, objetos STL, clases, etc. NO PUEDE pasar objetos c ++ a través de enlaces dll sin mucho diseño cuidadoso y mucha magia específica del compilador, o sufrimiento de la duplicación masiva de código de objeto en las diversas DLL, y como resultado una aplicación que es extremadamente sensible a la versión. Cualquier pequeño cambio a una definición de clase forzará una reconstrucción de todos los exe y dll, eliminando al menos uno de los principales beneficios de un enfoque dll para el desarrollo de la aplicación.
O se adhieren a una interfaz recta de C entre la aplicación y dll, sufren el infierno, o simplemente compilan toda la aplicación de c ++ como un exe.
nedmalloc? también NB que smplayer usa un parche especial para anular malloc, que puede ser la dirección en la que te diriges.