gpt4 book ai didi

更改调试的断言行为(SIGABRT -> SIGTRAP)

转载 作者:太空狗 更新时间:2023-10-29 15:38:38 24 4
gpt4 key购买 nike

我正在尝试调试使用 gcc/g++ 构建的 Debian 程序(DEBUG=1NDEBUG 未定义)。我正在使用第三方库,它也是为调试而构建的(DEBUG=1NDEBUG 未定义,以及其他调试定义)。该库有 150K 行,并且充满了断言。这很好。

我的代码有一个错误,我正在尝试调试 SQL 查询。它导致在第三方库中触发断言。这没问题,而且在类(class)中也很正常。

但是,当 assert 在库中触发时,那个脑残的 Posix 指定行为会使程序崩溃。在调试“debugging and diagnostic”功能时,这是无用的行为。这一定是该委员会做出的最愚蠢的决定之一,难怪许多人在开发过程中很少使用它。

我想更改行为,以便在触发断言时引发 SIGTRAP 而不是 SIGABRT。我有点受限,因为我没有编写第三方库(我的代码使用 MY_ASSERT,它调用 SIGTRAP,所以我可以继续查看负代码路径)。

我知道我可以通过 gdb 安装或更改信号处理程序,但是 gdb 在将它传递给程序并中止之前已经在 SIGABRT 上停止了。我还尝试安装一个自定义的 SIGABRT 信号处理程序,这似乎没有帮助,因为中止仍然发生。

如何更改 assert 的行为以在调试时引发 SIGTRAP

最佳答案

对于 linux,你可以定义一个 __assert_fail 可以引发 SIGTRAP 的函数,而不是默认实现。

void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) {
fprintf(stderr, "Assert: %s failed at %s:%d in function %s", assertion, file, line, function);
raise(SIGTRAP);
}

规范说你实际上应该在此时终止程序,因为函数被声明为具有 __attribute__((noreturn))。在signal.h .

您可以像这样添加一些不确定的代码(编辑为使用 ptrace 通过 fork 而不是信号进行检测):

#include <assert.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ptrace.h>

static int ptrace_failed;

static int
detect_ptrace(void)
{
int status, waitrc;

pid_t child = fork();
if (child == -1) return -1;
if (child == 0) {
if (ptrace(PT_ATTACH, getppid(), 0, 0))
exit(1);
do {
waitrc = waitpid(getppid(), &status, 0);
} while (waitrc == -1 && errno == EINTR);
ptrace(PT_DETACH, getppid(), (caddr_t)1, SIGCONT);
exit(0);
}
do {
waitrc = waitpid(child, &status, 0);
} while (waitrc == -1 && errno == EINTR);
return WEXITSTATUS(status);
}

__attribute__((constructor))
static void
detect_debugger(void)
{
ptrace_failed = detect_ptrace();
}

void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) {
fprintf(stderr, "Assert: %s failed at %s:%d in function %s\n", assertion, file, line, function);
if (ptrace_failed)
raise(SIGTRAP);
else
abort();
}

哪个触发 SIGTRAP在 gdb 下运行时,否则会触发 SIGABRT .我已经测试了它链接到LD_PRELOAD它似乎按预期工作。

关于更改调试的断言行为(SIGABRT -> SIGTRAP),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21257164/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com