我目前面临着glibc v2.22的问题,在那里我无法获得适当的展开信息。当有SIGABRT应用程序时,它将从glibc调用abort函数。它应该使用在构建中启用的展开信息。但是,它正在扫描堆栈(如屏幕快照中地址下面的红线所示),并提供所附屏幕快照中显示的误导性信息(使用哨兵分析转储)。
在这里,do_crash被调用,它执行assert(0),然后中止主应用程序。在分析转储时,do_crash函数调用_fini,这个_fini从来不在主应用程序的堆栈中。
我已经通过使用CFLAGS += "-funwind-tables"为glibc启用了展开。我也尝试过使用-rdynamic和-fno-omit-frame-pointer等标志,但这也没有用。
我是不是漏掉了什么?如何获得信号的完全回溯,特别是SIGABRT?
提前感谢

发布于 2022-08-04 09:15:28
当有SIGABRT应用程序时,它从glibc调用中止函数。
这不是真的,这种情况不会发生,除非您显式地注册了它。
i通过使用CFLAGS +=启用了glibc的展开
它告诉编译器添加信息,而不是“启用展开”。What exactly happens when compiling with -funwind-tables?
在这里,
调用了do_crash,它确实断言(0),然后中止主应用程序。
这与接收SIGABRT信号无关。
,我是不是漏掉了什么?
我相信你做了错误的假设--在SIGABRT上调用了一些东西,SIGABRT是在断言上发送的,而abort()是在SIGABRT上调用的。在SIGABRT上不调用任何东西,程序在默认情况下接收到SIGABRT时被终止(请参见man 7 signal),assert只是终止程序而不引发SIGABRT,而abort()则引发SIGABRT信号,而不是接收它。
如何获得信号的完全回溯,特别是SIGABRT?
注册一个将执行此操作的处理程序。见How to automatically generate a stacktrace when my program crashes。
#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
_Exit(1);
}
int main(int argc, char **argv) {
signal(SIGABRT, handler); // install our handler
raise(SIGABRT);
}如果您想要在assert()上打印堆栈跟踪,这是完全不同的,并且您将覆盖glibc处理程序来执行断言:
#include <assert.h>
#include <execinfo.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
void print_trace(void) {
void *array[10];
size_t size;
size = backtrace(array, 10);
backtrace_symbols_fd(array, size, STDERR_FILENO);
}
// based on https://code.woboq.org/userspace/glibc/assert/assert.c.html
void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function) {
extern const char *__progname;
fprintf(stderr, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",
__progname, __progname[0] ? ": " : "",
file, line,
function ? function : "", function ? ": " : "",
assertion);
print_trace();
abort();
}
int main() {
assert(0);
}https://stackoverflow.com/questions/69614422
复制相似问题