GNU/Linux >> Tutoriales Linux >  >> Linux

Vincular libstdc++ estáticamente:¿algún problema?

Es posible que también deba asegurarse de no depender de la glibc dinámica. Ejecutar ldd en su ejecutable resultante y tenga en cuenta las dependencias dinámicas (libc/libm/libpthread son sospechosos habituales).

Un ejercicio adicional sería construir un montón de ejemplos de C++11 involucrados utilizando esta metodología y probar los archivos binarios resultantes en un sistema 10.04 real. En la mayoría de los casos, a menos que haga algo extraño con la carga dinámica, sabrá de inmediato si el programa funciona o falla.


Esa entrada de blog es bastante imprecisa.

Por lo que sé, se han introducido cambios en la ABI de C++ con cada versión principal de GCC (es decir, aquellas con diferentes componentes de número de primera o segunda versión).

No es verdad. Los únicos cambios de ABI de C++ introducidos desde GCC 3.4 han sido compatibles con versiones anteriores, lo que significa que la ABI de C++ se ha mantenido estable durante casi nueve años.

Para empeorar las cosas, la mayoría de las principales distribuciones de Linux usan instantáneas de GCC y/o parchean sus versiones de GCC, lo que hace que sea prácticamente imposible saber exactamente con qué versiones de GCC puede estar tratando cuando distribuye archivos binarios.

Las diferencias entre las versiones parcheadas de GCC de las distribuciones son menores y no cambian la ABI, p. Fedora's 4.6.3 20120306 (Red Hat 4.6.3-2) es compatible con ABI con las versiones anteriores de FSF 4.6.x y casi seguro con cualquier 4.6.x de cualquier otra distribución.

En GNU/Linux, las bibliotecas de tiempo de ejecución de GCC usan el control de versiones de símbolos ELF, por lo que es fácil verificar las versiones de símbolos que necesitan los objetos y las bibliotecas, y si tiene un libstdc++.so que proporciona esos símbolos funcionará, no importa si es una versión parcheada ligeramente diferente de otra versión de su distribución.

pero ningún código C++ (o cualquier código que use el soporte de tiempo de ejecución de C++) puede vincularse dinámicamente si esto funciona.

Esto tampoco es cierto.

Dicho esto, enlazar estáticamente a libstdc++.a es una opción para ti.

La razón por la que podría no funcionar si carga dinámicamente una biblioteca (usando dlopen ) es que los símbolos libstdc++ de los que depende podrían no haber sido necesarios para su aplicación cuando la vinculó (estáticamente), por lo que esos símbolos no estarán presentes en su ejecutable. Eso se puede resolver vinculando dinámicamente la biblioteca compartida a libstdc++.so (que es lo correcto de todos modos si depende de ello). La interposición de símbolos ELF significa que los símbolos que están presentes en su ejecutable serán utilizados por la biblioteca compartida, pero otros que no están presentes en su ejecutable se encontrarán en cualquier libstdc++.so se vincula a. Si su aplicación no usa dlopen no es necesario que te preocupes por eso.

Otra opción (y la que prefiero) es implementar el nuevo libstdc++.so junto con su aplicación y asegúrese de que se encuentre antes que el sistema predeterminado libstdc++.so , lo que se puede hacer forzando al enlazador dinámico a buscar en el lugar correcto, ya sea usando $LD_LIBRARY_PATH variable de entorno en tiempo de ejecución, o configurando un RPATH en el ejecutable en tiempo de enlace. Prefiero usar RPATH ya que no depende de que el entorno esté configurado correctamente para que la aplicación funcione. Si vincula su aplicación con '-Wl,-rpath,$ORIGIN' (tenga en cuenta las comillas simples para evitar que el shell intente expandir $ORIGIN ) entonces el ejecutable tendrá un RPATH de $ORIGIN que le dice al enlazador dinámico que busque bibliotecas compartidas en el mismo directorio que el ejecutable. Si pones el nuevo libstdc++.so en el mismo directorio que el ejecutable se encontrará en tiempo de ejecución, problema resuelto. (Otra opción es poner el ejecutable en /some/path/bin/ y la nueva libstdc++.so en /some/path/lib/ y enlace con '-Wl,-rpath,$ORIGIN/../lib' o cualquier otra ubicación fija relativa al ejecutable, y establezca el RPATH relativo a $ORIGIN )


Una adición a la excelente respuesta de Jonathan Wakely, por qué dlopen() es problemático:

Debido al nuevo grupo de manejo de excepciones en GCC 5 (consulte PR 64535 y PR 65434), si abre y abre una biblioteca que está vinculada estáticamente a libstdc++, obtendrá una pérdida de memoria (del objeto del grupo) cada vez. Entonces, si existe alguna posibilidad de que alguna vez use dlopen, parece una muy mala idea vincular estáticamente libstdc ++. Tenga en cuenta que esta es una fuga real a diferencia de la benigna mencionada en PR 65434.


Linux
  1. Appnativefy:convierte cualquier sitio web en una imagen de aplicación única ejecutable

  2. ¿Cómo canalizar comandos a cualquier terminal?

  3. Nativefier:convierta fácilmente cualquier sitio web en una aplicación de escritorio

  4. iconv cualquier codificación a UTF-8

  5. ¿Alguna experiencia con Java en Raspberry PI?

Cómo hacer un archivo ejecutable en Linux

C/C++ con GCC:agrega estáticamente archivos de recursos al ejecutable/biblioteca

¿Por qué una carpeta debe ser ejecutable?

¿Cómo configurar un archivo como NO ejecutable?

Sudo contra raíz; alguna diferencia real?

Vinculación de interfaces Ethernet