Estoy tratando de compilar una biblioteca grande (TensorFlow) usando gcc en Ubuntu. Instalé la cadena de herramientas g ++ - arm-linux-gnueabihf, y pude construir con éxito mi binario. El proceso que estoy usando para construir está documentado aquí: https://github.com/petewarden4prs/tensorflow/tree/master/tensorflow/contrib/makefile#raspberry-pi
Inicialmente recibí un error de que pthreading estaba deshabilitado ("Habilitar subprocesos múltiples para usar std :: thread: Operación no permitida") cuando intenté ejecutar el ejecutable resultante en mi Pi 3. Recompilé con -pthread habilitado como una opción de compilación, y ahora el programa se bloquea aparentemente al azar con fallas de segmentación. Al ejecutarlo en gdb, a menudo parecen estar relacionados con free () que se llama con punteros incorrectos, y las pilas de llamadas parecen corruptas, por lo que supongo que está ocurriendo una falta de coincidencia de memoria.
¿Alguien tiene sugerencias sobre cosas que puedo tratar de rastrear qué está pasando aquí?
Aquí hay algunos detalles más de mi Pi:
pi@raspberrypi ~ $ uname -a
Linux raspberrypi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux
pi@raspberrypi ~ $ file benchmark
benchmark: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x5043384f5d0003f8074b07dfdd38cdc20315143f, not stripped
Aquí hay un ejemplo de una sesión típica en gdb:
[New Thread 0x76cf5450 (LWP 6011)]
*** glibc detected *** /home/pi/benchmark: free(): invalid pointer: 0x018e2e89 ***
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x76cf5450 (LWP 6011)]
0x76f98e40 in std::string::c_str() const () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
(gdb) thread apply all bt
Thread 2 (Thread 0x76cf5450 (LWP 6011)):
#0 0x76f98e40 in std::string::c_str() const () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#1 0x00bad996 in tensorflow::thread::ThreadPool::Impl::WorkerLoop() ()
#2 0x00bad5de in tensorflow::thread::ThreadPool::Impl::Impl(tensorflow::Env*, tensorflow::ThreadOptions const&, std::string const&, int)::{lambda()#1}::operator()() const ()
#3 0x00badec2 in std::_Function_handler<void (), tensorflow::thread::ThreadPool::Impl::Impl(tensorflow::Env*, tensorflow::ThreadOptions const&, std::string const&, int)::{lambda()#1}>::_M_invoke(std::_Any_data const&) ()
#4 0x0029aaf4 in std::function<void ()>::operator()() const ()
#5 0x00b53e1e in _ZNSt12_Bind_simpleIFSt8functionIFvvEEvEE9_M_invokeIJEEEvSt12_Index_tupleIJXspT_EEE ()
#6 0x00b53d90 in std::_Bind_simple<std::function<void ()> ()>::operator()() ()
#7 0x00b53d4a in std::thread::_Impl<std::_Bind_simple<std::function<void ()> ()> >::_M_run() ()
#8 0x76f91848 in ?? () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#9 0x76f91848 in ?? () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Thread 1 (Thread 0x76ff6000 (LWP 6010)):
#0 0x76dfc61c in ?? () from /lib/arm-linux-gnueabihf/libc.so.6
#1 0x76fff048 in ?? () from /lib/ld-linux-armhf.so.3
Cannot access memory at address 0x158
#2 0x76fff048 in ?? () from /lib/ld-linux-armhf.so.3
Cannot access memory at address 0x158
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
fuente
Respuestas:
La forma más fácil de una compilación cruzada compatible con binarios es instalar la cadena de herramientas utilizada por los desarrolladores de Raspbian. Se puede encontrar aquí . Es esencial usar esta cadena de herramientas si desea construir el kernel y los controladores, ya que los objetos del kernel requieren una compatibilidad ABI perfecta, pero tener compatibilidad perfecta no afectará si también está creando binarios de espacio de usuario.
Según la documentación , esta cadena de herramientas es compatible con Ubuntu actual, tanto de 32 bits como de 64 bits.
fuente
Estaba obteniendo una
pure virtual method called
excepción al realizar la compilación cruzada. La respuesta de @ JeremyBarnes no funcionó para mí. En su lugar, usé:Explicación :
Como señaló @JeremyBarnes, para garantizar la compatibilidad ABI de su aplicación con el stdc ++ instalado, ambos deben compilarse con los mismos
SYNC
indicadores.En Raspbian:
Sin la corrección
dockcross/linux-armv6
ydockcross/linux-armv7
:Con la corrección activada
dockcross/linux-armv6
ydockcross/linux-armv7
:fuente
FWIW, esto se puede solucionar agregando
-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
a los indicadores del compilador.¿Por qué? En /usr/include/c++/4.{8,9}/bits/concurrency.h, la política de bloqueo predeterminada depende de estas definiciones:
El ABI de un puntero compartido depende de cómo se definan estos indicadores, ya que hereda de una clase base que utiliza un argumento de plantilla predeterminado para la política de bloqueo. Por lo tanto, cambiar estos indicadores cambia el diseño (porque cambia el diseño de la clase base) de los objetos std :: shared_ptr <...> en la biblioteca estándar de C ++.
En el compilador que viene con el Pi, con el que se construyó Raspbian, se configuran de la siguiente manera:
Esto es sensato para el Pi 1, pero es una gran pena para el Pi 3, que puede usar felizmente punteros atómicos compartidos.
En Ubuntu, se configuran así:
Los indicadores de la línea de comando de arriba los restablecen a su estado predeterminado en el Pi.
La compilación cruzada vale la pena; Tensorflow ya es lento para construir en un servidor robusto; ¡Debe tomar un tiempo increíblemente largo para construir en el Pi!
fuente