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

Kri*_*fer 0 c++ coredump exception ada

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

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

raised STORAGE ERROR
Run Code Online (Sandbox Code Playgroud)

即使您在启动应用程序之前发出了"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.

小智 6

现在,差不多2年后(仍然在克里斯托弗在问这个问题的同一家公司工作),问题再次提出 - 最后我认为我理解为什么没有产生核心转储!!

问题是由Ada运行时引起的,该运行时默认为某些POSIX信号实现信号处理程序(对于Linux:SIGABRT,SIGFPE,SIGILL,SIGSEGV和SIGBUS).对于GNAT/Linux中的信号处理程序被调用__gnat_error_handlerA-INIT.C,它看起来是这样的:

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);
 }
Run Code Online (Sandbox Code Playgroud)

这个处理程序是"进程范围"的,并且将被任何触发信号调用,无论它来自哪个进程部分(无论是否在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);
Run Code Online (Sandbox Code Playgroud)

在您的Ada代码中 - 现在系统的默认行为将在引发SIGSEGV时触发,并且将生成核心转储,允许您追踪问题的根源!

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

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

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