【问题标题】:Struggling with using gdb to debug C++ code w/ Ada library努力使用 gdb 调试带有 Ada 库的 C++ 代码
【发布时间】:2013-02-20 22:45:00
【问题描述】:

由于各种原因,我无法详细说明,但这是我正在使用的基本架构

  • 我有一个 C++ 框架,它使用我构建的 C++ 目标文件来执行动态模拟。
  • C++ 库调用了一个用 Ada 编写的共享 (.so) 库。

据我所知,Ada 库(包含大量重要代码)在边缘情况下生成异常,但我无法隔离生成异常的函数。

这是我正在使用的:

  • CentOS 4.8(最终版)
  • gcc 3.4.6 (w/ gnat)
  • gdb 6.3.0.0-1.162.el4rh

这是我正常执行时遇到的错误:

terminate called without an active exception
raised PROGRAM_ERROR : unhandled signal

我可以让 gdb 在异常返回到 C++ 后立即捕获它,但我无法让它在 Ada 代码中捕获。我已确保使用-g 编译所有内容,但这似乎无助于解决问题。

当我尝试捕捉/中断gdb(礼貌地告诉我Catch of signal not yet implemented)中的信号/异常时,我得到了这个:

[Thread debugging using libthread_db enabled]
[New thread -1208371520 (LWP 14568)]
terminate called without an active exception
Program received signal SIGABRT, Aborted.
[Switching to thread -1208371520 (LWP 14568)]
0x001327a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2

我相信terminate called [...] 行来自框架。当我尝试捕获该中断,然后运行回溯 (bt) 时,我得到如下信息:

#0  0x001327a2 in gdb makes me want to flip tables.
#1  0x00661825 in raise () from /lib/tls/libc.so.6
#2  0x00663289 in abort () from /lib/tls/libc.so.6
#3  0x0061123e in __gnu_cxx: __verbose_terminate_handler () from /usr/lib/libstdc++.so.6
#4  0x0060eed1 in __xac_call_unexpected () from /usr/lib/libstdc++.so.6
#5  0x0060ef06 in std::terminate () from /usr/lib/libstdc++.so.6
#6  0x0060f0a3 in __xax_rethrow () from /usr/lib/libstdc++.so.6
#7  0x001fe526 in cpputil::ExceptionBase::Rethrow (scope=@0xbfe67470) at ExceptionBase.cpp:140

此时,它已进入框架代码。

我已经在线阅读了一些指南、教程和手册页,但我有点不知所措。我希望这里有人可以帮助我指出正确的方向。

【问题讨论】:

  • 你给 gdb 什么命令来捕获异常?
  • 我试过catch signal SIGABRT,但它回复了Catch of signal not yet implemented.,所以我用handle SIGABRT stop来尝试捕捉信号,但得到的结果与上面相似。我认为真正的问题,我不知道如何解决这个问题,是我无法打破 Ada 中未捕获的异常。当我尝试 catch exception(基于我在网上找到的一些 Ada 特定的 gdb 资料)时,我收到一个错误 Unknown event type specified for catch
  • 我相信您的 GDB 需要专门在 Ada 支持下构建。我在自己的工作中注意到“捕获异常”仅适用于专门针对 Ada 的 GDB 安装,例如由 AdaCore 分发的安装。
  • 这是完全可能的。我使用的是系统默认包含的任何版本的 gdb。我可以在各种 Ada 函数中设置正常断点并始终停止它们,但是捕捉这个断点让我很适应。用 Ada 支持重建 gdb 是我可以在本地做的事情,还是我需要从 AdaCore 之类的东西预构建它?
  • 你可以尝试在__gnat_unhandled_exception(源在s-excdeb.adss-excdeb.adb)尝试破解,这是一个在异常E的传播过程中调用的“[h]ook,尽快众所周知,它未被处理”。这可能为时已晚; __gnat_debug_raise_exception 在引发点被调用,但如果应用程序引发了许多它随后处理的异常,则将难以使用。

标签: c++ linux gcc gdb ada


【解决方案1】:

听起来您可以编译 Ada 源代码。假设是这种情况,在通过其执行引发异常的调用的子程序中,在转储异常信息的末尾添加一个异常处理程序:

when E : others =>
    Ada.Text_IO.Put_Line(Ada.Exceptions.Exception_Information(E));
    raise;

您还需要将 Ada.Exceptions 的“with”添加到包中。和 Ada.Text_IO,如果它不存在的话。

我不确定你会从那个版本的 GNAT 中得到什么,但它可能是你可以使用 addr2line 解码的调用地址。

【讨论】:

  • 这正是我所需要的。我必须在上面添加一个exception 行(以适应beginexceptionend 过程结构),但这让我在异常被传递给 C++ 代码并获得足够的信息之前捕获它跟随它的源头。我还没有解决这个问题,但我有我的前几个面包屑。谢谢!
【解决方案2】:

你能从 Ada main 启动 C++ 框架吗?如果是这样,并且您可以通过 C++ 框架将异常传播到 Ada 主程序,它的最后机会处理程序应该为您提供一个非常好的报告,其中包含异常、源文件和发生的行以及 addr2line 的堆栈转储。我对这些的经验是,之后通常不需要调试器。

我可能会在这里走神,因为我没有使用过任何像你一样古老的蚊子......

【讨论】:

  • 我还没有尝试从 Ada main 启动框架,但我不确定该怎么做。我正在开发团队中没有人完全理解的代码库。这无济于事,我的阿达夫比较弱。你有从 Ada main 内部启动框架的好例子吗?
  • 例如,遵循这种方法 - wiki.ada-dk.org/c_bindings_example(注意:-fdump-ada-spec 绑定生成器需要 gcc4.6 或更高版本,但如果您能发现 C++ 命名方案,您可以创建手动绑定)你大概只需要调用一个 C++ 函数。另外:我不知道 C++ 是否会避开并完整地传递异常。
  • 我不知道框架是否会让我通过函数调用开始它,但我明天会深入研究文档,看看我能不能做到这一点。
  • Alternative 可能是 C++ 和库之间的 Ada 包装器,具有异常处理功能。如果你需要包装几千个函数,那就没有吸引力了……
猜你喜欢
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
相关资源
最近更新 更多