C++获取“分段错误”的文件名和行号Linux x64

发布于 2024-11-01 20:44:05 字数 59 浏览 0 评论 0原文

不运行GDB,而只运行程序本身。

编辑:我已经见过这样的程序,但我不知道自己该怎么做:(

Without running GDB, but only the program itself.

edit: i've already seen such program but i can't figure how to do that myself :(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

生来就爱笑 2024-11-08 20:44:05

解决这个问题的汤米值得赞扬。

我通过使用 中有点标准的 backtrace 实用程序将他的答案与 GDB 分离。

static void dumpstack(void){
    static void *backbuf[ 50 ];
    int levels;

    levels = backtrace( backbuf, 50 );
    backtrace_symbols_fd( backbuf, levels, STDERR_FILENO );

    return;
}

您可以尝试打开文件并写入而不是 STDERR_FILENO,但我会避免在崩溃的进程中进行如此繁重的工作。

在我的系统上,输出如下所示:

Shadow:code dkrauss$ ./dumpy 
0   dumpy                               0x0000000100000d81 dumpstack + 25
1   dumpy                               0x0000000100000d18 signal_handler + 47
2   libSystem.B.dylib                   0x00007fff86b1766a _sigtramp + 26
3   ???                                 0x0000000000000000 0x0 + 0
4   dumpy                               0x0000000100000a18 start + 52
FATAL: Segmentation Fault

所以,它没有给出文件名+行号,但它确实给出了函数名+代码偏移量,您可以很容易地翻译它。

Tommie deserves credit for solving this.

I've detached his answer from GDB by using the somewhat standard backtrace utility from <execinfo.h>.

static void dumpstack(void){
    static void *backbuf[ 50 ];
    int levels;

    levels = backtrace( backbuf, 50 );
    backtrace_symbols_fd( backbuf, levels, STDERR_FILENO );

    return;
}

You can try opening a file and writing instead of STDERR_FILENO, but I'd avoid such heavy lifting in a crashed process.

On my system, the output looks like this:

Shadow:code dkrauss$ ./dumpy 
0   dumpy                               0x0000000100000d81 dumpstack + 25
1   dumpy                               0x0000000100000d18 signal_handler + 47
2   libSystem.B.dylib                   0x00007fff86b1766a _sigtramp + 26
3   ???                                 0x0000000000000000 0x0 + 0
4   dumpy                               0x0000000100000a18 start + 52
FATAL: Segmentation Fault

So, it doesn't give file name + line number, but it does give function name + code offset, which you can translate easily enough.

栀子花开つ 2024-11-08 20:44:05

嗯...您可以尝试这样做...

struct sigaction g_sigact;

void panic(const char *fmt, ...){
    char buf[PANICBUF_LEN];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, "%s\n", buf);
    exit(-1);
}
void init_signals(void){
    g_sigact.sa_handler = signal_handler;
    sigemptyset(&g_sigact.sa_mask);
    g_sigact.sa_flags = 0;
    sigaction(SIGINT, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &g_sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig){
    if (sig == SIGHUP) g_keepRunning = 0;
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if ((sig == SIGQUIT || (sig == SIGKILL) || (sig == SIGINT)) ;
}

static void dumpstack(void){
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    char dbx[160];
    sprintf(dbx, "echo -ne 'detach\n' | gdb --eval-command=where --pid=%d > %d.dump", getpid(), getpid());
    system(dbx);
    return;
}

当捕获分段错误时,会调用 dumpstack 并打印直到分段错误并被重定向时的最新堆栈跟踪到一个带有进程数字pid的文件......

Hmmm... you could try doing it this way...

struct sigaction g_sigact;

void panic(const char *fmt, ...){
    char buf[PANICBUF_LEN];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, "%s\n", buf);
    exit(-1);
}
void init_signals(void){
    g_sigact.sa_handler = signal_handler;
    sigemptyset(&g_sigact.sa_mask);
    g_sigact.sa_flags = 0;
    sigaction(SIGINT, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &g_sigact, (struct sigaction *)NULL);

    sigaddset(&g_sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &g_sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig){
    if (sig == SIGHUP) g_keepRunning = 0;
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if ((sig == SIGQUIT || (sig == SIGKILL) || (sig == SIGINT)) ;
}

static void dumpstack(void){
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    char dbx[160];
    sprintf(dbx, "echo -ne 'detach\n' | gdb --eval-command=where --pid=%d > %d.dump", getpid(), getpid());
    system(dbx);
    return;
}

When a segmentation fault is trapped, dumpstack gets invoked and prints the most recent stack-trace up to the point when it segmentation faulted and gets redirected to a file with a numeric pid of the process....

几味少女 2024-11-08 20:44:05

为什么你不想运行 gdb?如果使用它,您可以非常轻松地检测段错误的位置。

Why exactly do you not want to run gdb? You can detect the location of segfaults very easily if you use it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文