如何捕获SIGBUS错误

How to catch SIGBUS error?

本文关键字:错误 SIGBUS 何捕获      更新时间:2023-10-16

我正在尝试在只读内存上捕获错误但无法做到?如果我处理错误,那么程序可以继续还是唯一的选项是退出/中止?

#include<iostream>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
char * F00()
{
        char *s2="ab";
        return s2;
}
void InvalidMem()
{
                (F00())[0]='l';
}
void
termination_handler (int signum)
{
        fprintf(stderr,"BUS error");
}
int
main(int argc, char **argv)
{
        signal (SIGBUS, termination_handler);
        InvalidMem();
        for(int i = 0; i < 10; ++i)
                std::cout<<" L " ;
        return 0;
}

SIGBUS 表示您正在访问未对齐的地址,SIGSEGV

表示您正在访问您"不应该"访问的地址(无效地址或写入只读内存 - 在某些情况下,内存可以是只写的,从此类内存读取也会导致 SIGSEGV)。

由于处理器并不真正知道当您最终进入信号处理程序时它处于什么状态,因此在这些情况下通常不可能仅从信号处理程序本身继续。相反,典型的方法是使用setjmplongjmp来"恢复到已知点"。这可能是代码的"主循环",也可能是某个错误恢复点。

所以,像这样:

 jmp_buf reset;
 int termination_handler(int signum)
 {
     longjmp(reset, 1);
 }
 int main()
 {
    if (setjmp(reset) != 0)
    {
        printf("We got back from signal handler")
        ...
    }
    signal (SIGBUS, termination_handler);
    ...
    return 0;
 }

应该注意的是,如果您在执行错误(如总线故障或地址错误)后实际上"继续前进",您可能会遇到一些严重的麻烦 - 例如考虑:

// At global level:
  some_lock lock;
// in some function. 
  ....
  lock->take();
  some code that crashes;
  lock->release();

所以,现在锁被抓住了,并且从未释放过......下次您需要取锁时,代码可能会挂起...