Asignación de memoria en Static vs Dynamic Linking de C Runtime
visual-c++ dynamic-linking (3)
La arquitectura de mi programa incluye plugins (dlls) y el exe (obviamente). Somos el único proveedor de complementos. Me dijeron que asignar memoria en un complemento y luego liberarlo en el código exe era un problema potencial si vinculamos estáticamente el tiempo de ejecución c. Sin embargo, si lo vinculamos dinámicamente, solo había un montón y el tiempo de ejecución de C tenía acceso a todo. Cambiamos a la vinculación dinámica sobre la base de este consejo, pero todo lo que hemos visto desde el cambio son dolores de cabeza y problemas relacionados con la distribución e instalación de los nuevos tiempos de ejecución. (No sé lo que evitamos en términos de problemas de asignación de memoria).
¿Cuáles son las implicaciones de asignación de memoria? Digamos que un complemento asigna memoria y el exe lo libera. ¿Hay un comportamiento diferente entre el tiempo de ejecución estática vs dinámicamente vinculado? ¿Tendremos problemas para vincular estáticamente el tiempo de ejecución c si usamos complementos? Si volvemos a la vinculación estática, ¿estropeará la detección de fuga de memoria y el informe de volcado de emergencia?
Está en línea con algunas preguntas planteadas por los comentarios sobre ¿Qué versión de tiempo de ejecución de VC ++ elijo, estática o dinámica? específicamente ¿Qué versión de tiempo de ejecución de VC ++ elijo, estática o dinámica?
También hay un debate en http://msdn.microsoft.com/en-us/library/abx4dbyh(v=VS.100).aspx .
Las funciones para asignar / memoria libre están emparejadas; no puede llamar a my_malloc () y luego usar free (), o llamar al operador "nuevo" de C ++ y luego llamar a FreeMem () desde alguna biblioteca aleatoria :)
Su complemento necesita una forma bien conocida de asignar y liberar memoria. Si lo hace malloc (), entonces su programa principal probablemente solo puede hacer free (). Pero si hace algo más exótico (Windows tiene toneladas de asignadores de memoria disponibles), su API de complemento necesita proporcionar una forma para que el principal ejecute el complemento para liberar sus datos.
Entonces, si tu programa principal llama
foo = plugin->allocate_something()
entonces sería aconsejable que su API de complemento tenga un correspondiente
plugin->free_something (foo)
que el programa principal puede usar inequívocamente.
Obviamente, el problema es que el complemento y la aplicación principal usan administradores de montón diferentes e incompatibles que se enfrentan a las estructuras de datos de los demás. El uso de un CRT dinámico teóricamente obliga a ambos a usar el mismo CRT y, por lo tanto, ambos son automáticamente compatibles.
En el caso general, es mejor que el complemento sea responsable de asignar y eliminar toda la memoria que utiliza. Esto implica la posibilidad de agregar API al complemento para eliminar los objetos que creó anteriormente y volver a pasar a la aplicación principal. Esto también proporciona un buen aislamiento entre el complemento y la aplicación, lo que permite que el complemento use asignadores especializados por rendimiento u otras razones. Esto es lo que COM hace, por ejemplo.
Si desea asignar desde el montón en un módulo y liberarlo en otro, simplemente tiene que vincular dinámicamente el tiempo de ejecución. Además, todas las partes deben vincular dinámicamente el mismo tiempo de ejecución. Una vez que hagas eso, entonces no habrá problemas.
Ahora bien, esta es una restricción bastante severa para imponer a sus complementos y debería pensarlo dos veces antes de hacerlo. Obligar a todos los autores de complementos a actualizarse en el paso de bloqueo es una gran imposición. Le recomendaría que considere la refacturación de su interfaz para que las asignaciones siempre estén emparejadas con desasignaciones dentro de un único módulo. Esto elimina las limitaciones que describo arriba y hace la vida más fácil para sus autores de complementos.
En cuanto a por qué todavía sufre de errores de tiempo de ejecución, es difícil de decir. Supongo que no todos los módulos están vinculados con la misma versión del tiempo de ejecución.
En los comentarios indica que controla todos los complementos. Eso significa que las limitaciones que analizo anteriormente no son una imposición, ya que es fácil para usted usar la misma versión de compilación para todos los módulos. Sin embargo, las reglas para la vinculación dinámica con el acceso a heap de módulos cruzados permanecen. Debe usar enlaces dinámicos contra la misma versión única del tiempo de ejecución.