包含ada dll的崩溃C ++应用程序不会生成核心转储

时间:2010-02-10 11:14:30

标签: c++ exception ada coredump

如何获取包含加载的ada共享库的C ++应用程序,以便在崩溃时生成核心转储

我有一个加载ada共享库的C ++应用程序,在ada代码中我遇到堆栈溢出错误导致程序终止以及控制台输出:

raised STORAGE ERROR

即使您在启动应用程序之前发出了“ulimit -c unlimited”,也不会生成核心转储文件。

如果我向应用程序发送kill SIGSEGV ,也会发生同样的事情。

将kill SIGSEGV 发送到另一个不使用ada dll的应用程序,就像我想要的那样生成核心转储文件。

在此处找到一些信息:http://objectmix.com/ada/301203-gnat-fstack-check-does-work.html

已更新! 正如Adrien所提到的,没有矛盾, -s 设置堆栈限制,而 -c 设置核心文件限制。

问题仍然存在。我在构建ada库时检查了标志,并且未设置 fstack-check 标志,因此它应该生成核心转储。

我还没试过,看起来有点奇怪。 它提到-fstack-check编译器选项+设置GNAT_STACK_LIMIT变量但同时引用ulimit命令似乎是一个矛盾,设置“ulimit -c”是我知道生成核心转储的唯一方法在崩溃时,如果这与fstack-check选项有关,那么我们有一个捕获22。

4 个答案:

答案 0 :(得分:6)

现在,差不多两年后(仍然在Kristofer问他问题的同一家公司工作),问题再次提出 - 最后我认为我理解为什么没有生成核心转储!!

问题是由Ada运行时引起的,该运行时默认为某些POSIX信号实现信号处理程序(对于Linux:SIGABRT,SIGFPE,SIGILL,SIGSEGV和SIGBUS)。对于GNAT / linux,信号处理程序在 a-init.c 中称为 __ gnat_error_handler ,如下所示:

static void
__gnat_error_handler (int sig)
{
  struct Exception_Data *exception;
  char *msg;
  static int recurse = 0;
  ...
  switch (sig)
    {
    case SIGSEGV:

      if (recurse)
      {
        exception = &constraint_error;
        msg = "SIGSEGV";
      }
      else
      {
        ...
        msg = "stack overflow (or erroneous memory access)";
        exception = &storage_error;
      }
      break;
     }
    recurse = 0;
    Raise_From_Signal_Handler (exception, msg);
 }

这个处理程序是“进程范围”,并且将被任何触发信号调用,无论它来自哪个进程部分(无论是否在Ada / C / C ++中编码......)。

当被调用时,处理程序引发Ada异常并将其留给Ada运行时以找到适当的异常处理程序 - 如果没有找到这样的处理程序(例如,当C ++的任何部分生成SIGSEGV时 - 代码) ,Ada-runtime回退到只是终止进程,只留下 __ gnat_error_handler 的简单打印输出(例如“堆栈溢出(或错误的内存访问)”)。

http://www2.adacore.com/gap-static/GNAT_Book/html/node25.htm

为防止Ada-runtime处理POSIX信号并将其转换为Ada异常,可以使用

禁用默认beahviour

pragma Interrupt_State(Name => value,State => SYSTEM | RUNTIME | USER);

例如。要禁用SIGSEGV的处理,请定义

Pragma Interrupt_State(SIGSEGV, SYSTEM);
在您的Ada代码中

- 现在系统的默认行为将在引发SIGSEGV时被触发,并且将生成核心转储,以便您追踪问题的根源!

我认为在* NIX平台上混合使用Ada和C / C ++时,这是一个非常重要的问题,因为它可能误导您认为问题源于Ada代码(因为打印输出表示异常)当问题的真正根源在于C / C ++ - 代码......

时,从Ada生成)

虽然禁用对SIGSEGV的Ada-runtime默认处理可能是安全的(我想没有理智的程序员在任何“预期的”错误处理中使用它......好吧,也许用在航空软件或类似的,当某种类型的“最后的手段”功能需要保持以避免发生非常糟糕的事情。)我想应该采取一点谨慎然后“覆盖”Ada运行时处理信号。

一个问题可能是SIGFPE信号,默认情况下也会引发Ada Constraint_Error异常。 Ada代码可以将此类异常用作“被排除的行为”。 通过Pragma Interrupt_State禁用SIGFPE可能会严重影响Ada代码的执行,并在“正常情况下”使应用程序崩溃 - 另一方面,在C / C ++中将任何除零 - 代码触发Ada异常处理机制,让你没有任何真正的问题根源......

答案 1 :(得分:1)

这让我觉得真的很适合您的AdaCore支持。你不会在公司外发现很多熟悉Gnu Ada运行时和C ++之间相互作用的人。

我建议您调试Ada代码,尝试在最后一个异常处理程序中放入所有内容,然后转储异常堆栈。大多数供应商都有一些方法,通常基于Ada.Exceptions.Exception_Information和Ada.Exceptions.Exception_Message。

答案 2 :(得分:0)

我从安全角度找到a discussion(发现恶意软件)。基本上你可以尝试10个信号,SIGSEGV只是其中之一。

答案 3 :(得分:0)

您似乎只需调用sigaction(SIGSEGV, 0, SIG_DFL);即可恢复默认信号行为。