gpt4 book ai didi

c++ - 在 C 和 C++ 中捕获 SIGBUS

转载 作者:太空宇宙 更新时间:2023-11-04 07:30:56 25 4
gpt4 key购买 nike

我想抓SIGBUS,我的代码如下:

#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

最佳答案

您不能在信号处理程序中使用 printfcout。您也不能调用 exit。这次您很幸运地使用了 printf,但是您没有像使用 cout 那样幸运。如果您的程序处于不同的状态,也许 cout 会工作而 printf 不会。或者两者都不是,或者两者都不是。检查操作系统的文档,了解哪些功能是信号安全的(如果存在,通常记录得很糟糕)。

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

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

#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;
}

关于c++ - 在 C 和 C++ 中捕获 SIGBUS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13834643/

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