O que está causando essas falhas após a compilação cruzada?


8

Estou tentando compilar uma biblioteca grande (TensorFlow) usando o gcc no Ubuntu. Instalei a cadeia de ferramentas g ++ - arm-linux-gnueabihf e consegui construir com êxito o meu binário. O processo que estou usando para criar está documentado aqui: https://github.com/petewarden4prs/tensorflow/tree/master/tensorflow/contrib/makefile#raspberry-pi

Inicialmente, encontrei um erro que o pthreading estava desativado ("Ativar o multithreading para usar std :: thread: operação não permitida") quando tentei executar o executável resultante no meu Pi 3. Recompilei com -pthread ativado como uma opção de compilação e agora o programa trava aparentemente aleatoriamente com falhas de segmentação. Ao executá-lo em gdb, eles geralmente parecem relacionados ao free () ser chamado com ponteiros ruins e as pilhas de chamadas parecem corrompidas, então estou assumindo que há alguma incompatibilidade de memória acontecendo.

Alguém tem sugestões sobre coisas que eu posso tentar rastrear aqui?

Aqui estão mais alguns detalhes do meu 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

Aqui está um exemplo de uma sessão típica no 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?)

11
O seu código é 32 bits ou 64? Também tenho um projeto que quero trabalhar, mas recebo um despejo semelhante "Não é possível acessar a memória .....".
Dan V

2
Apenas como uma atualização, acabei abandonando a compilação cruzada, pois parece menos usada que a compilação nativa e era mais difícil depurar problemas como esse.
Pete Warden

Respostas:


3

A maneira mais fácil de uma compilação cruzada compatível com binário é instalar o conjunto de ferramentas usado pelos desenvolvedores do Raspbian. Pode ser encontrado aqui . É essencial usar essa cadeia de ferramentas se você deseja construir o kernel e os drivers, pois os objetos do kernel exigem compatibilidade ABI perfeita, mas ter compatibilidade perfeita não será prejudicial se você também estiver construindo binários do espaço do usuário.

De acordo com a documentação , essa cadeia de ferramentas é compatível com o atual Ubuntu, de 32 e 64 bits.


3

Eu estava recebendo uma pure virtual method calledexceção ao fazer a compilação cruzada. A resposta de @ JeremyBarnes não funcionou muito bem para mim. Em vez disso, usei:

-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8

Explicação :

Como o @JeremyBarnes apontou, para garantir a compatibilidade ABI do seu aplicativo com o stdc ++ instalado, ambos precisam ser compilados com os mesmos SYNCsinalizadores.

Em Raspbian:

$ g++ -dM -E - < /dev/null | grep SYNC
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1

Sem a correção dockcross/linux-armv6e dockcross/linux-armv7:

$ g++ -dM -E - < /dev/null | grep SYNC
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1

Com a correção ativada dockcross/linux-armv6e dockcross/linux-armv7:

$ g++ -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2  -E - < /dev/null | grep SYNC
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1

2

FWIW, isso pode ser corrigido adicionando -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8aos sinalizadores do compilador.

Por quê? Em /usr/include/c++/4.{8,9}/bits/concurrency.h, a política de bloqueio padrão depende dos seguintes parâmetros:

#if (definido (__ GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
     && definido (__ GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))

A ABI de um ponteiro compartilhado depende de como esses sinalizadores são definidos, pois herda de uma classe base que usa um argumento de modelo padrão para a política de bloqueio. Portanto, alterar esses sinalizadores altera o layout (porque altera o layout da classe base) dos objetos std :: shared_ptr <...> na biblioteca C ++ padrão.

No compilador que acompanha o Pi, com o qual o Raspbian foi criado, eles são definidos da seguinte maneira:

g ++ -dM -E - </ dev / null | grep SYNC
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1

Isso é sensato para o Pi 1, mas é uma grande vergonha para o Pi 3, que pode usar alegremente ponteiros compartilhados atômicos.

No Ubuntu, eles são configurados assim:

arm-linux-gnueabihf-g ++ -dM -E - </ dev / null | grep SYNC
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1

Os sinalizadores da linha de comando acima os redefinem como estão por padrão no Pi.

A compilação cruzada vale a pena; O Tensorflow já é lento para construir em um servidor robusto; deve levar um tempo incrivelmente longo para desenvolver o Pi!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.