首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C和C++捕获SIGBUS

用C和C++捕获SIGBUS
EN

Stack Overflow用户
提问于 2012-12-12 15:13:00
回答 2查看 4.6K关注 0票数 1

我想要捕获SIGBUS,我的代码如下:

代码语言:javascript
复制
#include <stdlib.h>
#include <signal.h>
#include <iostream>
#include <stdio.h>

void catch_sigbus (int sig)
{
    //std::cout << "SIGBUS" << std::endl;
    printf("SIGBUS\n");   
    exit(-1);
}


int main(int argc, char **argv) {

signal (SIGBUS, catch_sigbus);

    int *iptr;
    char *cptr;

#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

    /* malloc() always provides aligned memory */
    cptr = (char*)malloc(sizeof(int) + 1);

    /* Increment the pointer by one, making it misaligned */
    iptr = (int *) ++cptr;

    /* Dereference it as an int pointer, causing an unaligned access */

    *iptr = 42;

    return 0;
}

当我使用printf时,它可以通过调用catch_sigbus来捕获,但是当我使用cout时,它不能。所以有人能帮我吗?我在Ubuntu 12.04上运行。

我还有一个问题。当我捕捉到SIGBUS时,我怎样才能得到si_code?BUS_ADRALN/BUS_ADRERR/BUS_OBJERR

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-12 16:19:05

不能在信号处理程序中使用printfcout。也不能调用exit。这一次您在printf上走运了,但在cout上就没那么走运了。如果你的程序处于不同的状态,也许cout可以工作,而printf不能工作,或者两者都不能工作。检查您的操作系统的文档,以了解哪些函数是信号安全的(如果存在,它的文档通常非常糟糕)。

在这种情况下,最安全的方法是直接将write调用到STDERR_FILENO,然后调用_exit (而不是exit,因为它在信号处理程序中是不安全的)。在某些系统上,将fprintf调用到stderr是安全的,但我不确定glibc是否是其中之一。

编辑:要回答添加的问题,您需要使用sigaction设置信号处理程序以获取附加信息。这个例子就是我在一个信号处理程序中所用到的,如果你想更进一步的话,我提供了一个替代的方法。请注意,write在理论上是不安全的,因为它会破坏errno,但由于我们使用的是_exit,所以在这种情况下它是安全的

代码语言:javascript
复制
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

void
bus_handler(int sig, siginfo_t *si, void *vuctx)
{
        char buf[2];
#if 1
        /*                                                                                                                           
         * I happen to know that si_code can only be 1, 2 or 3 on this                                                               
         * particular system, so we only need to handle one digit.                                                                   
         */
        buf[0] = '0' + si->si_code;
        buf[1] = '\n';
        write(STDERR_FILENO, buf, sizeof(buf));
#else
        /*                                                                                                                           
         * This is a trick I sometimes use for debugging , this will                                                                 
         * be visible in strace while not messing with external state too                                                            
         * much except breaking errno.                                                                                                
         */
        write(-1, NULL, si->si_code);
#endif
        _exit(1);
}

int
main(int argc, char **argv)
{
        struct sigaction sa;
        char *cptr;
        int *iptr;

        memset(&sa, 0, sizeof(sa));

        sa.sa_sigaction = bus_handler;
        sa.sa_flags = SA_SIGINFO;
        sigfillset(&sa.sa_mask);
        sigaction(SIGBUS, &sa, NULL);

#if defined(__GNUC__)
# if defined(__i386__)
        /* Enable Alignment Checking on x86 */
        __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
        /* Enable Alignment Checking on x86_64 */
        __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

        /* malloc() always provides aligned memory */
        cptr = (char*)malloc(sizeof(int) + 1);

        /* Increment the pointer by one, making it misaligned */
        iptr = (int *) ++cptr;

        /* Dereference it as an int pointer, causing an unaligned access */

        *iptr = 42;

        return 0;
}
票数 3
EN

Stack Overflow用户

发布于 2012-12-12 16:18:39

根据您的评论,您正在尝试调试SIGBUS,并且已经存在关于这一点的问题:Debugging SIGBUS on x86 Linux

它列出了许多可能的原因。但SIGBUS最有可能的原因是,你的内存崩溃了,它搞砸了事情,所以你以后会得到SIGBUS……因此,调试信号可能对解决错误没有帮助。也就是说,使用调试器捕获代码中抛出信号的点,并查看它是否是指针。对于试图找出原因,这是一个很好的起点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13834643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档