【问题标题】:Invoking debugger from within a C program从 C 程序中调用调试器
【发布时间】:2012-07-16 07:05:45
【问题描述】:
我正在阅读 David Hanson 的《C 接口和实现》一书。这个练习题似乎很有趣,但我无法找到解决方案:
在某些系统上,当程序有
检测到错误。该设施在
开发,当断言失败可能很常见时。
您能否提供一个关于如何调用调试器的简短示例。
void handle_seg_fault(int arg)
{
/* how to invoke debugger from within here */
}
int main()
{
int *ptr = NULL;
signal(SIGSEGV, handle_seg_fault);
/* generate segmentation fault */
*ptr = 1;
}
【问题讨论】:
-
无论你做什么,确保你只在你的信号处理程序中使用async signal safe functions。例如,在所有exec 变体中,只有execve 和execle 可以在(异步信号捕获)信号处理程序的上下文中安全执行。现在,这样做通常是否明智(面对像 SIGSEGV 这样的“状态破坏信号”)是另一回事。我会选择 (a) 外部调试器或 (b) 检查 coredump 事后分析。
标签:
c
linux
gdb
systems-programming
【解决方案1】:
详细阐述 Christian.K 的评论,fork()面对 SIGFPE 或 SIGSEGV 之类的调试器可能不是最好的想法,因为...
- 您的程序可能一开始就已损坏,导致
fork() 不安全;
- 您可能希望使用与程序硬编码不同的东西进行调试;
- 一般应用程序用户不知道如何处理调试器;
- 任何有能力拥有调试器的人通常更喜欢coredump而不是自动调用的调试器。
我可以复制到测试平台的核心转储在一天中的任何时间都能胜过客户工作场所的调试器实例。调试器界面会导致糟糕的最终用户错误消息。
【解决方案2】:
我有这个:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
void exception_handler(int)
{
int pid = getpid();
if (fork() != 0) {
while(true) sleep(1000);
}
char buf[20];
sprintf(buf, "--pid=%u", pid);
execlp("gdb", "gdb", buf, NULL);
exit(-1);
}
int init()
{
if (signal(SIGSEGV, exception_handler) < 0) {
return errno;
}
if (signal(SIGILL, exception_handler) < 0) {
return errno;
}
if (signal(SIGFPE, exception_handler) < 0) {
return errno;
}
return 0;
}
int main()
{
if (int rc = init()) {
fprintf(stderr, "init error: %s\n", strerror(rc));
return 1;
}
*((char*)(0)) = 1;
}