Was verursacht diese Abstürze nach dem Cross-Compilieren?


8

Ich versuche, eine große Bibliothek (TensorFlow) mit gcc unter Ubuntu zu kompilieren. Ich habe die Toolkette g ++ - arm-linux-gnueabihf installiert und konnte meine Binärdatei erfolgreich erstellen. Der Prozess, den ich zum Erstellen verwende, ist hier dokumentiert: https://github.com/petewarden4prs/tensorflow/tree/master/tensorflow/contrib/makefile#raspberry-pi

Anfangs habe ich den Fehler festgestellt, dass pthreading deaktiviert war ("Multithreading aktivieren, um std :: thread zu verwenden: Operation nicht zulässig"), als ich versuchte, die resultierende ausführbare Datei auf meinem Pi 3 auszuführen Jetzt stürzt das Programm scheinbar zufällig mit Segmentierungsfehlern ab. Wenn sie es in gdb ausführen, scheinen sie oft damit zu tun zu haben, dass free () mit schlechten Zeigern aufgerufen wird, und die Aufrufstapel scheinen beschädigt zu sein. Ich gehe also davon aus, dass eine Speicherinkongruenz vorliegt.

Hat jemand Vorschläge zu Dingen, mit denen ich versuchen kann, herauszufinden, was hier falsch läuft?

Hier sind einige weitere Details von meinem 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

Hier ist ein Beispiel für eine typische Sitzung in 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
Ist Ihr Code 32bit oder 64? Ich habe auch ein Projekt, das ich zum Laufen bringen möchte, aber ich erhalte einen ähnlichen Speicherauszug "Kann nicht auf Speicher zugreifen ....." Wir haben ihn auf die Inkompatibilität der 32-Bit-Umgebung zurückgeführt.
Dan V

2
Nur als Update habe ich die Cross-Kompilierung aufgegeben, da sie weniger gut genutzt zu werden scheint als die native Kompilierung und es schwieriger war, solche Probleme zu debuggen.
Pete Warden

Antworten:


3

Der einfachste Weg zu einer binär kompatiblen Cross-Kompilierung besteht darin, die von Raspbian-Entwicklern verwendete Toolchain zu installieren. Es kann hier gefunden werden . Es ist wichtig, diese Toolchain zu verwenden, wenn Sie den Kernel und die Treiber erstellen möchten, da Kernelobjekte eine perfekte ABI-Kompatibilität erfordern. Eine perfekte Kompatibilität schadet jedoch nicht, wenn Sie auch Userspace-Binärdateien erstellen.

Laut Dokumentation ist diese Toolchain mit dem aktuellen 32-Bit- und 64-Bit-Ubuntu kompatibel.


3

pure virtual method calledBeim Cross-Compilieren wurde eine Ausnahme angezeigt. @ JeremyBarnes 'Antwort hat bei mir nicht ganz funktioniert. Stattdessen habe ich verwendet:

-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8

Erklärung :

Wie @JeremyBarnes hervorhob, müssen beide mit denselben SYNCFlags kompiliert werden, um die ABI-Kompatibilität Ihrer Anwendung mit dem installierten stdc ++ sicherzustellen .

Auf Raspbian:

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

Ohne das Update auf dockcross/linux-armv6und 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

Mit dem Fix auf dockcross/linux-armv6und 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, dies kann durch Hinzufügen -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8zu den Compiler-Flags behoben werden .

Warum? In /usr/include/c++/4.{8,9}/bits/concurrency.h hängt die Standardsperrrichtlinie von folgenden Definitionen ab:

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

Der ABI eines gemeinsam genutzten Zeigers hängt davon ab, wie diese Flags definiert sind, da er von einer Basisklasse erbt, die ein Standardvorlagenargument für die Sperrrichtlinie verwendet. Durch Ändern dieser Flags wird daher das Layout (da es das Basisklassenlayout ändert) der std :: shared_ptr <...> -Objekte in der Standard-C ++ - Bibliothek geändert.

In dem Compiler, der mit dem Pi geliefert wird, mit dem Raspbian erstellt wurde, werden sie wie folgt festgelegt:

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

Dies ist für den Pi 1 sinnvoll, aber eine große Schande für den Pi 3, der gerne atomare gemeinsame Zeiger verwenden kann.

Unter Ubuntu sind sie folgendermaßen eingerichtet:

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

Die obigen Befehlszeilenflags setzen sie auf den Standardwert auf dem Pi zurück.

Cross Compiling lohnt sich; Tensorflow baut auf einem bulligen Server bereits langsam auf. Es muss unglaublich lange dauern, um auf dem Pi aufzubauen!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.