Tengo una aplicación multiplataforma de C++ que se divide en varias bibliotecas compartidas y carga funcionalidades adicionales de las bibliotecas compartidas de los complementos. Se supone que las bibliotecas de complementos son autónomas y funcionan por sí mismas, sin conocimiento o dependencia de la aplicación de llamada.Segfault en la biblioteca de complementos de C++ con símbolos duplicados
Uno de los complementos contiene código copiado de la aplicación principal, por lo que contiene nombres de símbolos que están duplicados en el motor. (Sí, sé que generalmente es un no-no, pero en el momento en que se escribió el complemento el motor era un binario monolítico y no podía compartir bibliotecas.) En Windows, todo funciona bien. En Linux obtuvimos segfaults. Al observar el rastro de pila del error, estaba ocurriendo en el complemento al llamar funciones en el nombre de clase duplicado. Parecía ser un resultado de que el motor y el complemento tenían versiones ligeramente diferentes del código compartido (algunas funcionalidades de clase se comentaron en el complemento). Era como si el plugin obtuviera su tiempo de ejecución de símbolos vinculado al motor en lugar del propio. "Solucionamos" el problema cambiando los parámetros dlopen
para que sean dlopen(pFilepath, RTLD_LAZY | RTLD_LOCAL)
.
Pero cuando reescribimos el motor para dividirlo en bibliotecas compartidas (para el propósito final de la reutilización en los complementos), obtenemos el error segfault nuevamente. Y mirando el rastro de la pila, va desde el motor -> plugin -> motor.
¿Hay alguna manera de especificar que el enlazador de tiempo de ejecución no asigne símbolos del complemento al motor (especialmente si están definidos en el complemento)?
Gracias! Matt
Editado 2009-12-3
primera vez que trató de envolver el código del plug-in en su propio espacio de nombres. Eso no funcionó porque está vinculado estáticamente a una biblioteca que también está vinculada al motor. Las versiones de la biblioteca estática son diferentes, ¡así que segfault!
Luego modifiqué la construcción del motor y sus bibliotecas para que estuvieran vinculadas estáticamente. Y cuando lo ejecuto, ya no tengo el problema. Por lo tanto, parece que fue el resultado de exportar los símbolos de la biblioteca compartida y luego reubicarlos dinámicamente en el complemento cuando se abrió. Pero cuando todo el código del motor está en un único ejecutable, no exporta sus símbolos (por lo que no intenta reubicar los símbolos del complemento en el motor).
Todavía tengo un problema, ya que hay una versión paralela del programa (usando Open-MPI) y que aún recibe la segfault. Parece que sigue exportando los símbolos del motor y reubicando el plugin. Eso podría tener que ver con cómo Open-MPI ejecuta la aplicación.
¿Hay indicadores de enlazador que se podrían utilizar en la biblioteca compartida del complemento que indicaría que no se reubiquen dinámicamente los símbolos en el tiempo de ejecución? ¿O esconder sus símbolos para que no se reubiquen? Intenté -s
("Omitir toda la información del símbolo") pero aparentemente no cambió los símbolos dinámicos (verificados usando nm -D <plugin>
).
¿Son estos símbolos globales o nombres de funciones? ¿Puedes hacer pequeños cambios al código? –
Son clases y sus funciones miembro. Hay 36 archivos utilizados desde la base de código del motor, por lo que no quiero modificar el nombre o archivo de cada clase. Si bien el objetivo final es volver a escribir el complemento, debido a las limitaciones de tiempo y la validación del código, no quiero hacerlo si no es necesario. – CuppM
@CuppM, entonces, por ejemplo, ¿tienes una clase "Foo" con una "barra" miembro definida en 2 lugares? Y "Foo" está en el mismo espacio de nombres en ambos casos? Si es así, esto nunca funcionará correctamente para usted. Mueve uno de los "Foo" a su propio espacio de nombres y la vida será más fácil. – Glen