链接Boost库时程序退出但没有错误

3
我有一个问题,需要将boost库链接到我的交叉编译的C++程序中。我使用CodeSourcery在Ubuntu 12.04下为ARM目标(Pandaboard,也是Ubuntu 12.04)交叉编译代码。编译不带库的简单测试程序没有问题,甚至静态库的OpenCV也能正常工作。
但是,当链接boost 1.52.0库时出现了问题:
使用链接boost线程库(-lboost_thread -lboost_system)交叉编译程序时,程序编译无误,但在目标上执行时什么都没有发生。
程序像从未被执行过一样,没有任何错误提示。
在不链接boost库的情况下使用CodeSourcery进行交叉编译:目标上一切正常。使用g++在本地编译也完全正确。
为了测试目的,我将代码精简为以下几行:(即使不使用chrono函数,仅链接就会出现错误)
main.cpp
#include <iostream>
using namespace std;

#include<boost/chrono.hpp>

int main(int argc, char* argv[]) {

    cout << "!!!this test worked!!!" << endl;

    return 0;
}

链接器命令是(在Eclipse之外):
arm-none-linux-gnueabi-g++ -L/home/xy/arm-none-linux-gnueabi/lib -o "testARM" ./src/main.o -lpthread -lboost_thread -lboost_system

boost-libraries是使用CodeSourcery arm-none-linux-gnueabi-g++进行交叉编译的,遵循这个指南。我将它们全部复制到目标机器的/usr/lib文件夹中,并将/usr/lib添加到PATH和LD_LIBRARY_PATH中。
我尝试了使用eclipse进行远程调试,结果也一样:启动程序后,程序立即终止,但没有任何提示。
它甚至不输出错误信息或抱怨缺少某些内容。所以,我现在无法想到更多可以搜索的内容,因为我已经尝试过了...
您能否给我一些提示,让我能够尝试修复这个问题呢?
非常感谢!
更新:
当我使用strace运行我的测试程序时,日志包含以下信息:
$ vi strace-testARM.log
22:23:56.511385 execve("./testARM", ["./testARM"], [/* 17 vars */]) = 0
22:23:56.512789 brk(0)                  = 0xfae000
22:23:56.512972 uname({sys="Linux", node="panda", ...}) = 0
22:23:56.514010 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
22:23:56.514315 mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6f9b000
22:23:56.514498 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
22:23:56.514742 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
22:23:56.514986 fstat64(3, {st_mode=S_IFREG|0644, st_size=52288, ...}) = 0
22:23:56.515353 mmap2(NULL, 52288, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb6f72000
22:23:56.515536 close(3)                = 0
22:23:56.515688 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
22:23:56.515902 open("/lib/arm-linux-gnueabihf/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
22:23:56.516207 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\5P\0\0004\0\0\0"..., 512) = 512
22:23:56.516451 lseek(3, 66332, SEEK_SET) = 66332
22:23:56.516573 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1400) = 1400
22:23:56.516787 lseek(3, 65924, SEEK_SET) = 65924
22:23:56.516909 read(3, "A6\0\0\0aeabi\0\1,\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 55) = 55
22:23:56.517153 fstat64(3, {st_mode=S_IFREG|0755, st_size=100802, ...}) = 0
22:23:56.517519 mmap2(NULL, 107024, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb6f57000
22:23:56.517642 mprotect(0xb6f67000, 28672, PROT_NONE) = 0
22:23:56.517794 mmap2(0xb6f6e000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xf) = 0xb6f6e000
22:23:56.517977 mmap2(0xb6f70000, 4624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6f70000
22:23:56.518160 close(3)                = 0
22:23:56.518313 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
22:23:56.518557 open("/lib/arm-linux-gnueabihf/tls/v7l/neon/vfp/libboost_thread.so.1.52.0", O_RDONLY|O_CLOEXEC) = -1 EN


更新2:

我正在Ubuntu主机上编译我的程序,将文件传输到Pandaboard上,并按照@ShaunMarko的建议输入以下命令:

`ldd testARM` =>  `not a dynamic executable`

`file testARM` => `testARM: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped`

`file libboost_thread.so.1.52.0` => `libboost_thread.so.1.52.0: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped`

在编译g++表达式时,如果添加-v -H参数,我会收到以下内容:
... /xy/CodeSourcery/bin/../lib/gcc/arm-none-linux-gnueabi/4.7.2/../../../../arm-none-linux-gnueabi/include/boost/utility/result_of.hpp

COLLECT_GCC_OPTIONS='-O0' '-g3' '-Wall' '-c' '-fmessage-length=0' '-v' '-H' '-MMD' '-MP' '-MF' 'main.d' '-MT' 'main.d' '-o' 'main.o' '-shared-libgcc' '-march=armv5te' '-mtls-dialect=gnu' '-funwind-tables' '-D' '__CS_SOURCERYGXX_MAJ__=2012' '-D' '__CS_SOURCERYGXX_MIN__=9' '-D' '__CS_SOURCERYGXX_REV__=64'
 /xy/CodeSourcery/bin/../lib/gcc/arm-none-linux-gnueabi/4.7.2/../../../../arm-none-linux-gnueabi/bin/as -v -march=armv5te -meabi=5 -o main.o /tmp/cceTwLmn.s
GNU assembler version 2.23.51 (arm-none-linux-gnueabi) using BFD version (Sourcery CodeBench Lite 2012.09-64) 2.23.51.20120829
COMPILER_PATH=/xy/CodeSourcery/bin/../libexec/gcc/arm-none-linux-gnueabi/4.7.2/:/xy/CodeSourcery/bin/../libexec/gcc/:/xy/CodeSourcery/bin/../lib/gcc/arm-none-linux-gnueabi/4.7.2/../../../../arm-none-linux-gnueabi/bin/
LIBRARY_PATH=/xy/CodeSourcery/bin/../lib/gcc/arm-none-linux-gnueabi/4.7.2/:/xy/CodeSourcery/bin/../lib/gcc/:/xy/CodeSourcery/bin/../lib/gcc/arm-none-linux-gnueabi/4.7.2/../../../../arm-none-linux-gnueabi/lib/:/xy/CodeSourcery/bin/../arm-none-linux-gnueabi/libc/lib/:/xy/CodeSourcery/bin/../arm-none-linux-gnueabi/libc/usr/lib/
COLLECT_GCC_OPTIONS='-O0' '-g3' '-Wall' '-c' '-fmessage-length=0' '-v' '-H' '-MMD' '-MP' '-MF' 'main.d' '-MT' 'main.d' '-o' 'main.o' '-shared-libgcc' '-march=armv5te' '-mtls-dialect=gnu' '-funwind-tables' '-D' '__CS_SOURCERYGXX_MAJ__=2012' '-D' '__CS_SOURCERYGXX_MIN__=9' '-D' '__CS_SOURCERYGXX_REV__=64'

**** Build Finished ****

(这是最后一部分,上面列出了大量包含头文件的内容。xy-Path 是 CodeSourcery 安装在我的主目录中的位置)


你能否在目标设备上使用strace(https://wiki.ubuntu.com/Strace)运行你的程序? - Shaun Marko
谢谢您的回答。我已经发布了上面的strace日志。您能从中得出任何有用的信息吗? - Felix
你确定在ARM目标上运行了“ldd testARM”吗?同时在你的测试程序和相关的libboost_thread库上运行“file”命令。 - Shaun Marko
在调用g++时,使用-v -H选项查看包含哪些头文件以及链接到可执行文件的库可能也很有用。 - Shaun Marko
是的,所有操作都是通过SSH终端在目标设备上运行的。请查看我的问题中更新2以获取结果。 这有帮助吗? - Felix
显示剩余3条评论
1个回答

3

构建ARM应用程序的一般规则(实际上对于任何平台都必须是正确的)

您必须使用相同的ABI编译整个程序,并链接与兼容的库集。

在您的情况下,最后一项看起来像 /usr/lib/libboost_thread.so.1.52.0,由于它也与您的使用相关,请确保 libboost_thread 与您交叉编译主机上的匹配。

22:23:56.546298 open("/usr/lib/libboost_thread.so.1.52.0", O_RDONLY|O_CLOEXEC) = 3
22:23:56.546481 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\324\331\0\0004\0\0\0"..., 512) = 512
22:23:56.546755 lseek(3, 121020, SEEK_SET) = 121020
22:23:56.546878 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1200) = 1200
22:23:56.547091 lseek(3, 119052, SEEK_SET) = 119052
22:23:56.547213 read(3, "A(\0\0\0aeabi\0\1\36\0\0\0\0055TE\0\6\4\10\1\t\1\22\4\24\1\25"..., 41) = 41
22:23:56.547396 exit_group(1)           = ?

使用 ARM 系统时,你可以有许多库的变体,例如不同的 ABI 或 VFP/NEON 支持。使用现成的工具链可能无法默认匹配你的目标,因为它是为 ARM 设计的。 更新 如果你查看以前的日志
22:23:56.515902 open("/lib/arm-linux-gnueabihf/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
22:23:56.516207 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\5P\0\0004\0\0\0"..., 512) = 512
22:23:56.516451 lseek(3, 66332, SEEK_SET) = 66332
22:23:56.516573 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1400) = 1400
22:23:56.516787 lseek(3, 65924, SEEK_SET) = 65924
22:23:56.516909 read(3, "A6\0\0\0aeabi\0\1,\0\0\0\0057-A\0\6\n\7A\10\1\t\2\n\4\22"..., 55) = 55

您看到两件事情,首先是从路径中看到您的系统是hf。在读取的数据中,我们还看到7-A,这可能意味着与您的libboost_thread库中可能意味着ARMv5TE相比,ARMv7-A。您应该使用工具链中的readelf获取有关elf文件的信息,而不是使用file实用程序。

我建议使用-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard编译boost,并将生成的二进制文件放在`/usr/lib/vfp`下。

我认为阅读Debian网站上的vfp材料可以帮助您极大地理解情况,您应该自己进行小练习,而不是处理boost的编译过程。


谢谢这个提示,我现在对ABI和abihf进行了一些研究(显然是Ubuntu 12.04的默认设置)。我现在尝试使用标志-mfloat-abi=hard以及-mfloat-abi=softfp编译完整的boost库和我的程序,但不幸的是,在两种情况下都没有改变。 - Felix
从我目前所读的内容来看,我能想象的一件事是程序在运行时混淆了硬浮点库和软浮点库。有没有一种方法可以强制执行程序,只搜索所需的共享库?(例如 libstdc++ 等) /usr/lib/ 文件夹中有一个,/usr/lib/arm-linux-gnueabihf 中也有一个,我需要说“使用这个”。 - Felix
经过多次重新编译和库复制,您的建议真的起作用了。使用“-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard”编译了boost和我的程序,现在它可以正常工作了。非常感谢@auselen。 - Felix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接