Error de enlace al compilar la operación atómica gcc en modo de 32 bits
Pregunta
Tengo el siguiente programa:
~/test> cat test.cc
int main()
{
int i = 3;
int j = __sync_add_and_fetch(&i, 1);
return 0;
}
Estoy compilando este programa usando GCC 4.2.2 en Linux que se ejecuta en una máquina Intel de 64 bits con varias CPU:
~/test> uname --all
Linux doom 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux
Cuando compilo el programa en modo de 64 bits, compila y enlaza bien:
~/test> /share/tools/gcc-4.2.2/bin/g++ test.cc
~/test>
Cuando lo compilo en modo de 32 bits, aparece el siguiente error:
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccEVHGkB.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test>
Aunque en realidad nunca voy a ejecutar un procesador de 32 bits, necesito un ejecutable de 32 bits para poder vincularme con algunas bibliotecas de 32 bits.
Mis 2 preguntas son:
-
¿Por qué recibo un error de enlace cuando compilo en modo de 32 bits?
-
¿Hay alguna forma de hacer que el programa se compile y se enlace, sin dejar de poder vincularse con una biblioteca de 32 bits?
Solución
De la página GCC en Atomic Construidos :
No todas las operaciones son compatibles con Todos los procesadores de destino. Si un particular la operación no se puede implementar en el procesador de destino, una advertencia será generado y una llamada externa Se generará la función. los la función externa llevará lo mismo nombre como el incorporado, con un sufijo adicional `_n 'donde n es el tamaño del tipo de datos.
A juzgar por la salida del compilador, que se refiere a __sync_add_and_fetch_4
, esto es lo que está sucediendo. Por alguna razón, GCC no está generando la función externa correctamente.
Esta es probablemente la razón por la que solo obtiene un error en el modo de 32 bits: al compilar para el modo de 64 bits, se compila para su procesador más de cerca. Al compilar para 32 bits, puede estar usando un arco genérico (i386, por ejemplo) que no admite de forma nativa esas características. Intente especificar una arquitectura específica para su familia de chips (Xeon, Core 2, etc.) a través de -mcpu y vea si eso funciona.
Si no, tendrá que descubrir por qué GCC no incluye la función apropiada que debería estar generando.
Otros consejos
La respuesta de Dan Udey fue cercana, lo suficientemente cerca como para permitirme encontrar la solución real.
De acuerdo con la página man " -mcpu " es un sinónimo obsoleto de " -mtune " y solo significa "optimizar para una CPU en particular (pero aún se ejecuta en CPU más antiguas, aunque menos óptimas)". Intenté esto y no resolvió el problema.
Sin embargo, " -march = " significa "generar código para una CPU en particular (y no ejecutar en CPU más antiguas)". Cuando probé esto, resolvió el problema: al especificar una CPU de i486 o mejor se eliminó el error de enlace.
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccYnYLj6.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i386 test.cc
/tmp/ccOr3ww8.o(.text+0x22): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i486 test.cc
~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=pentium test.cc