Điều gì gây ra những sự cố sau khi biên dịch chéo?


8

Tôi đang cố gắng biên dịch chéo một thư viện lớn (TensorFlow) bằng gcc trên Ubuntu. Tôi đã cài đặt g ++ - chuỗi công cụ arm-linux-gnuispihf và có thể xây dựng thành công nhị phân của mình. Quá trình tôi đang sử dụng để xây dựng được ghi lại ở đây: https://github.com/petewarden4prs/tensorflow/tree/master/tensorflow/contrib/makefile#raspberry-pi

Ban đầu, tôi gặp lỗi khi pthreading bị vô hiệu hóa ("Cho phép đa luồng sử dụng std :: thread: Thao tác không được phép") khi tôi cố chạy kết quả thực thi trên Pi 3. Tôi đã biên dịch lại với -pthread được bật dưới dạng tùy chọn biên dịch và bây giờ chương trình gặp sự cố dường như ngẫu nhiên với các lỗi phân đoạn. Chạy nó trong gdb, chúng thường có vẻ liên quan đến free () bị gọi với các con trỏ xấu và các ngăn xếp cuộc gọi có vẻ bị hỏng, vì vậy tôi cho rằng có một số lỗi bộ nhớ xảy ra.

Có ai có đề xuất về những điều tôi có thể cố gắng theo dõi những gì sai ở đây không?

Dưới đây là một số chi tiết từ Pi của tôi:

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

Đây là một ví dụ về một phiên thông thường trong 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
Mã của bạn là 32bit hay 64? Tôi cũng có một dự án tôi muốn làm việc nhưng tôi nhận được một kết xuất tương tự "Không thể truy cập bộ nhớ ....." Chúng tôi đã theo dõi nó để không tương thích với Môi trường 32 bit.
Dan V

2
Cũng như một bản cập nhật, cuối cùng tôi đã từ bỏ việc biên dịch chéo, vì nó dường như ít được sử dụng hơn so với việc biên dịch riêng và khó gỡ lỗi hơn như các vấn đề như thế này.
Pete Warden

Câu trả lời:


3

Cách dễ nhất để biên dịch chéo tương thích nhị phân là cài đặt chuỗi công cụ được sử dụng bởi các nhà phát triển Raspbian. Nó có thể được tìm thấy ở đây . Việc sử dụng chuỗi công cụ này là điều cần thiết nếu bạn muốn xây dựng kernel và trình điều khiển, vì các đối tượng kernel yêu cầu khả năng tương thích ABI hoàn hảo, nhưng khả năng tương thích hoàn hảo sẽ không bị tổn thương nếu bạn cũng xây dựng các nhị phân không gian người dùng.

Theo tài liệu , chuỗi công cụ này tương thích với Ubuntu hiện tại, cả 32 bit và 64 bit.


3

Tôi đã nhận được một pure virtual method calledngoại lệ khi biên dịch chéo. Câu trả lời của @ JeremyBarnes không hoàn toàn phù hợp với tôi. Thay vào đó tôi đã sử dụng:

-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8

Giải thích :

Như @JeremyBarnes đã chỉ ra, để đảm bảo khả năng tương thích ABI của ứng dụng của bạn với stdc ++ đã cài đặt, cả hai cần phải được biên dịch với cùng một SYNCcờ.

Trên Raspbian:

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

Nếu không sửa lỗi 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

Với bản sửa lỗi trên 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, điều này có thể được sửa bằng cách thêm -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8vào các cờ biên dịch.

Tại sao? Trong /usr/include/c++/4. Đũa8,9spl / bits / conurrency.h, chính sách khóa mặc định phụ thuộc vào các định nghĩa sau:

#if (được xác định (__ GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) \
     && được xác định (__ GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))

ABI của một con trỏ dùng chung phụ thuộc vào cách xác định các cờ này, vì nó thừa hưởng từ một lớp cơ sở sử dụng đối số mẫu mặc định cho chính sách khóa. Do đó, việc thay đổi các cờ này sẽ thay đổi bố cục (vì nó thay đổi bố cục lớp cơ sở) của các đối tượng std :: shared_ptr <...> trong thư viện C ++ tiêu chuẩn.

Trong trình biên dịch đi kèm với Pi, với Raspbian được xây dựng, chúng được đặt như sau:

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

Điều này hợp lý với Pi 1, nhưng là một sự xấu hổ lớn cho Pi 3 có thể khá vui khi sử dụng các con trỏ chia sẻ nguyên tử.

Trên Ubuntu, chúng được thiết lập như thế này:

arm-linux-gnuispihf-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

Các cờ dòng lệnh ở trên đặt lại chúng theo cách mặc định trên Pi.

Biên dịch chéo là giá trị nó; Tensorflow đã chậm để xây dựng trên một máy chủ mạnh mẽ; phải mất một thời gian dài vô cùng để xây dựng trên Pi!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.