【问题标题】:Ada program on Linux: SIGSEGV due to missing file?Linux 上的 Ada 程序:SIGSEGV 由于缺少文件?
【发布时间】:2012-04-12 00:07:09
【问题描述】:

我使用以下命令在 Ubuntu 5.4 (GNAT 3.4) 上为 Linux 编译了 Ada 程序:

gnatmake -O3 myprogram -bargs -static

然后,当我在 Ubuntu 机器上运行该程序时,它运行良好。但是在另一台机器(Linux 网络服务器)上,当我尝试strace 时收到以下错误消息:

execve("./myprogram", ["./myprogram"], [/* 15 vars */]) = 0
brk(0)                                  = 0x811e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f8000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f7000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb76f7680, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++

这是什么意思?我是否正确理解程序无法运行是因为缺少两个文件(ld.so.nohwcap 和 ld.so.preload)?我怎样才能避免这个错误?编译时是否有可能将这些文件包含到程序中?

【问题讨论】:

  • 您看到的输出不一定(实际上可能不)意味着 segv 和丢失的文件之间存在联系。你会一直在 strace 中看到这种东西;这只是系统在寻找例如一个可能存在也可能不存在的预加载库。如果您的程序中有调试符号,gdb 是跟踪 segv 的更好工具。我已经很久没有调试 ADA 了,所以我不确定该怎么做。
  • 另外,您是在网络服务器上构建程序,还是将二进制文件复制过来?如果是后者,请尝试在那里构建它。
  • 我复制了二进制文件。但这是必要的,因为网络服务器上缺少 GNAT。而且我不允许在那里安装新软件包。

标签: linux ubuntu ada gnat


【解决方案1】:

这是什么意思?

这意味着您的程序试图取消引用 NULL 指针并以 SIGSEGV 终止

由于缺少两个文件(ld.so.nohwcap 和 ld.so.preload)而导致程序无法运行,我是否理解正确?

否:这些文件不存在是完全正常的,您的问题与它们无关。

  1. 用于调试此类问题的工具是gdbstrace 很少用于此类调试。
  2. 与流行的看法相反,完全静态的可执行文件(就像您构建的那样)在 Linux 上是较少可移植的,然后是动态链接的。特别是,您可能在链接时收到警告,类似于此:

    Using 'initgroups' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

    如果是这样,并且如果您的构建和网络服务器机器上安装的 glibc 版本不同,那么这正是你的问题。不要忽略此类警告(并且不要将您的可执行文件与-static 标志链接)。

更新:

是否可以只将缺少的 libgnat 包含到程序中?

有可能:您要做的是安排最后的链接行如下所示:

gcc ... -Wl,-Bstatic -lgnat -Wl,-Bdynamic ...

我不知道如何使用gnatmake 实现这一目标。

另一个可能更简单的替代方案:您是否考虑在服务器上安装libgnat-3.4.so.1

【讨论】:

  • 我没有看到这个警告。但现在我重新编译了没有-static-bargs 标志的程序。 strace 输出更长,不再包含 SIGSEGV KILL。所以看起来更好。但是当我用ldd 检查依赖项时,它说linux-gate.so.1 => (0xffffe000) libgnat-3.4.so.1 => not found libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb786c000) libc.so.6 => /lib/libc.so.6 (0xb7726000) /lib/ld-linux.so.2 (0xb7893000)。我怎样才能解决这个问题?是否可以只将缺少的libgnat 包含到程序中?
  • 非常感谢您的回答和补充!解决依赖关系非常重要,因为这种依赖关系是我的程序的ldd 输出与预编译的有效输出之间的唯一区别。因此,如果我解除对 libgnat 的依赖,程序将(可能)运行。
  • 我想我发现了问题:我安装了gnat-3.4,它依赖于gcc-3.4。但是我在这个系统上不仅有gcc-3.4,还有gcc-4.0。所以也许编译器使用了太新的 4.0 版本。会不会是这个原因?
  • 那么gnatlink呢?这不就是将共享库集成到编译好的程序中吗?
  • 终于解决了将LD_LIBRARY_PATH设置为本地目录并将缺少的依赖项放在那里的问题。非常感谢!
【解决方案2】:

您从 strace 看到的输出是试图在库中链接的动态链接器

  1. 我可以向您推荐运行 ldd 这将向您显示依赖项
  2. 修复依赖项,如果这不起作用
  3. 如果您重新编译它,请使用 -g 标志稍后对其进行调试
  4. 如果它仍然没有运行,请使用 gdb 并运行它,如果它在 where 中使用 SIGSEV 类型退出

旁注:始终确保 CPU“完全”相同,否则在新机器上重新编译它并将可执行文件作为二进制文件传输

The Man Page which is nice to be read

【讨论】:

  • lddstatically linked 因为我使用了参数-static
  • 感谢您提供这些通用且有用的提示!
【解决方案3】:

另外请记住,将在一台 Linux 机器(Ubuntu 5.4)上编译的程序移动到另一台(网络服务器)可能具有不同的文件依赖关系。特别是如果它们基于不同的发行版。以下是对 ld.so.* 文件的描述:scroll to the bottom

尝试 jimw 的建议并在网络服务器上构建程序。 GNAT 3.4 是旧版本,因此它可能无法在网络服务器上使用。还请记住,受雇俄罗斯人的建议 - 不要使用-static 标志。您可以尝试在没有 -static 标志的情况下在 Ubuntu 上重新编译您的程序并在网络服务器上运行新版本,但这可能无法解决错误。

如果在网络服务器上重新编译和/或编译它不起作用,您将不得不使用 gdb 来调试您的程序。或者您可以在此处发布部分代码,看看是否有人可以帮助您。

【讨论】:

  • 谢谢!编译没有-static 标志的程序有帮助。最后,复制所有缺失的依赖项并设置LD_LIBRARY_PATH 解决了剩下的问题。
猜你喜欢
  • 1970-01-01
  • 2018-07-25
  • 2019-07-23
  • 1970-01-01
  • 2014-09-19
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 2017-12-11
相关资源
最近更新 更多