如何获取包含加载的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。
答案 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异常,可以使用
禁用默认beahviourpragma 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);
即可恢复默认信号行为。