Aquí está el escenario:
- libA.so y libB.so están vinculados estáticamente al mismo STL.
- libA.so tiene una API pública que devuelve un std :: string.
- libB.so llama a esta función y recibe una copia de la cadena.
- Cuando la copia de la cadena libB.so sale del alcance, se llama al destructor de la cadena.
- La aplicación seg falla al intentar liberar la cadena copiada.
He leído en otros lugares que vincular estáticamente como este es malo, pero me gustaría entender mejor por qué es malo. ¿Alguien puede explicar por qué la secuencia anterior se bloquearía?
c++
libraries
stl
static-linking
user1509041
fuente
fuente
Respuestas:
Pensemos en esto con mucho cuidado. libA.so está estáticamente vinculado con el STL. Sin embargo, el STL no existe de forma aislada, requiere el tiempo de ejecución C (CRT). Ambos residen en libstdc ++. Una biblioteca estática. Esto significa que libA.so y libB.so tienen estructuras de datos CRT separadas. En particular, el montón usado por libA.so es diferente del montón usado por libB.so. Asignar una cadena del montón de tiempo de ejecución de libA e intentar liberarse del tiempo de ejecución de libB simplemente no funcionará porque el tiempo de ejecución de libB no tiene registros de asignación de la cadena. La única forma de destruir correctamente la cadena es llamando al destructor dentro de libA.so.
Uno podría preguntar: pero libB.so recibe una copia de la cadena, ¿verdad? Sí, eso es correcto, pero ¿quién ha asignado esta copia? Se ha asignado utilizando el constructor de copia dentro del contexto del tiempo de ejecución de libA.
Dicho esto, aún puede usar la cadena de libB.so. Simplemente no puedes destruirlo desde allí.
También puede permitir que libB reciba un puntero a la cadena y luego cree una copia dentro del contexto del tiempo de ejecución de libB. Esa copia puede ser destruida por libB.
Y es por eso que el enlace estático a veces es malo.
fuente
std::string
entonces el problema simplemente no existe: olibB.so
recibe una copia de la cadena, con la memoria administrada en su propia memoria, o recibirá una referencia / puntero a la cadenalibA.so
y no intentará eliminar la cadena de su propia memoria.El STL se llama "lleno de estado" (como opuesto a "sin estado"), lo que significa que tiene algunas cosas estáticas en su interior. Cuando vincula STL estáticamente a libA.so y libB.so, obtiene dos instancias de la biblioteca STL en la memoria en tiempo de ejecución (con dos copias de material estático). Cada una de esas dos copias administra los recursos asignados de forma independiente y los recursos asignados en una instancia de la biblioteca no se pueden liberar en otra
fuente