交叉编译后是什么导致这些崩溃?


8

我正在尝试在Ubuntu上使用gcc交叉编译大型库(TensorFlow)。我已经安装了g ++-arm-linux-gnueabihf工具链,并且能够成功构建我的二进制文件。我正在使用的构建过程记录在这里:https : //github.com/petewarden4prs/tensorflow/tree/master/tensorflow/contrib/makefile#raspberry-pi

最初,我尝试在Pi 3上运行生成的可执行文件时遇到一个错误,指出pthreading被禁用(“启用多线程以使用std :: thread:不允许操作”)。我重新编译了-pthread作为编译选项,并且现在,该程序似乎因分段错误而随机崩溃。在gdb中运行它,它们似乎经常与使用错误的指针调用free()有关,并且调用堆栈似乎已损坏,因此我假设发生了一些内存不匹配的情况。

有没有人对我可以尝试在这里找出问题的建议?

以下是我的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

这是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?)

1
您的代码是32位还是64位?我也有一个我想开始工作的项目,但我得到了类似的转储“无法访问内存.....”,我们将其追溯到32位环境不兼容。
Dan V

2
作为一个更新,我最终放弃了交叉编译,因为它似乎不如本机编译好用,并且调试此类问题更加困难。
皮特·沃登

Answers:


3

二进制兼容的交叉编译的最简单方法是安装Raspbian开发人员使用的工具链。可以在这里找到。如果要构建内核和驱动程序,则必须使用此工具链,因为内核对象需要完美的ABI兼容性,但是如果您还要构建用户空间二进制文件,则具有完美的兼容性也不会受到损害。

根据文档,此工具链与当前的32位和64位Ubuntu兼容。


3

pure virtual method called交叉编译时出现异常。@JeremyBarnes的回答对我来说不太有效。相反,我使用了:

-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8

说明

正如@JeremyBarnes指出的,要确保应用程序与已安装的stdc ++的ABI兼容性,它们都需要使用相同的SYNC标志进行编译。

在Raspbian上:

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

没有修复dockcross/linux-armv6dockcross/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

修复dockcross/linux-armv6dockcross/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,可以通过添加-D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8到编译器标志来解决此问题。

为什么?在/usr/include/c++/4.{8,9}/bits/concurrency.h中,默认锁定策略取决于以下定义:

#if(已定义(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\
     &&定义(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))

共享指针的ABI取决于如何定义这些标志,因为它是从对锁定策略使用默认模板参数的基类继承而来的。因此,更改这些标志会更改标准C ++库中std :: shared_ptr <...>对象的布局(因为它会更改基类的布局)。

在树莓派附带的Pi附带的编译器中,它们的设置如下:

g ++ -dM -E-</ dev / null | grep同步
#定义__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1

这对于Pi 1来说是明智的,但对于可以很高兴地使用原子共享指针的Pi 3来说却是一大耻辱。

在Ubuntu上,它们的设置如下:

arm-linux-gnueabihf-g ++ -dM -E-</ dev / null | grep同步
#定义__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
#定义__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
#定义__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#定义__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1

上面的命令行标志将它们重置为Pi上的默认状态。

交叉编译是值得的;在强大的服务器上构建Tensorflow已经很慢了。必须花费非常长的时间才能在Pi上构建!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.