Rock姜 2022-10-30 09:43 采纳率: 60%
浏览 166
已结题

linux 系统内无法捕获SIGSEGV信号

不知道为什么在linux系统内无法捕获SIGSEGV信号。但是控制台已经报出了Segmentation fault (core dumped)
。下面是代码和控制台信息。 我的目的是要在代码中捕获SIGSEGV信号。我只是想知道我为什么无法从代码中捕获SIGSEGV信号。以及我如何才能够在代码中捕获如下的SIGSEGV信号。


#include <cstring>
#include "threadTest.hpp"
#include "iostream"
#include "pthread.h" //线程 锁
#include "unistd.h"  //睡眠
#include "semaphore.h"//信号量
#include "signal.h"
#include "errno.h"
#include "stdlib.h"

struct BigObj {
    char* a1="a";
    char* a2="a";
    char* a3="a";
    char* a4="a";
    char* a5="a";
    char* a6="a";
    char* a7="a";
    char* a8="a";

    char* a9="a";
    char* a10="a";
    char* a11="a";
    char* a12="a";
    char* a13="a";
    char* a14="a";
    char* a15="a";
    char* a16="a";

    char* a17="a";
    char* a18="a";
    char* a19="a";
    char* a20="a";
    char* a21="a";
    char* a22="a";
    char* a23="a";
    char* a24="a";

    char* a25="a";
    char* a26="a";
    char* a27="a";
    char* a28="a";
    char* a29="a";
    char* a30="a";
    char* a31="a";
    char* a32="a";

    char* a33="a";
    char* a34="a";
    char* a35="a";
    char* a36="a";
    char* a37="a";
    char* a38="a";
    char* a39="a";
    char* a40="a";

    char* a41="a";
    char* a42="a";
    char* a43="a";
    char* a44="a";
    char* a45="a";
    char* a46="a";
    char* a47="a";
    char* a48="a";

    char* a49="a";
    char* a50="a";
    char* a51="a";
    char* a52="a";
    char* a53="a";
    char* a54="a";
    char* a55="a";
    char* a56="a";

    char* a57="a";
    char* a58="a";
    char* a59="a";
    char* a60="a";
    char* a61="a";
    char* a62="a";
    char* a63="a";
    char* a64="a";

    char* a65="a";
    char* a66="a";
    char* a67="a";
    char* a68="a";
    char* a69="a";
    char* a70="a";
    char* a71="a";
    char* a72="a";
};
static void add_error_signals_to_set(sigset_t* set) {
    sigaddset(set, SIGILL);
    sigaddset(set, SIGBUS);
    sigaddset(set, SIGFPE);
    sigaddset(set, SIGSEGV);
    sigaddset(set, SIGTRAP);
}

static void remove_error_signals_from_set(sigset_t* set) {
    sigdelset(set, SIGILL);
    sigdelset(set, SIGBUS);
    sigdelset(set, SIGFPE);
    sigdelset(set, SIGSEGV);
    sigdelset(set, SIGTRAP);
}
static unsigned int index_t = 0;
static void* stack;
void signal_SIGSEGV_handler(int sig) {
    void *frame_addr = __builtin_frame_address(0);
    printf("Got tid=%p SIGSEGV at address: 0x%lx\n", pthread_self(), frame_addr);
    exit(EXIT_FAILURE);
}
void signal_SIGBUS_handler(int sig) {
    void *frame_addr = __builtin_frame_address(0);
    printf("Got pid=%p SIGBUS at address: 0x%lx\n", pthread_self(), frame_addr);
    exit(EXIT_FAILURE);
}
void signal_SIGABRT_handler(int sig) {
    void *frame_addr = __builtin_frame_address(0);
    printf("Got pid=%p SIGABRT at address: 0x%lx\n", pthread_self(), frame_addr);
    exit(EXIT_FAILURE);
}
void signal_SIGIO_handler(int sig) {
    void *frame_addr = __builtin_frame_address(0);
    printf("Got pid=%p SIGIO at address: 0x%lx\n", pthread_self(), frame_addr);
    exit(EXIT_FAILURE);
}
void signal_SIGCHLD_handler(int sig) {
    void *frame_addr = __builtin_frame_address(0);
    printf("Got pid=%p SIGCHLD at address: 0x%lx\n", pthread_self(), frame_addr);
    exit(EXIT_FAILURE);
}
static void javaSignalHandler(int sig, siginfo_t* info, void* ucVoid) {
    void *frame_addr = __builtin_frame_address(0);
    printf("Got pid=%p javaSignalHandler at address: 0x%lx\n", pthread_self(), frame_addr);
    exit(EXIT_FAILURE);
}
void set_signal_handler(int sig, bool do_check = true) {
    struct sigaction oldAct;
    sigaction(sig, (struct sigaction*)NULL, &oldAct);

    struct sigaction sigAct;
    sigfillset(&(sigAct.sa_mask));
    remove_error_signals_from_set(&(sigAct.sa_mask));
    sigAct.sa_sigaction = javaSignalHandler;
    sigAct.sa_flags = SA_SIGINFO|SA_RESTART;

    int ret = sigaction(sig, &sigAct, &oldAct);
    printf("ERROR ret:%d\n", ret);
}
#include "alloca.h"
typedef unsigned char* address;
void *thread_function(void *arg) {
    void *frame_addr = __builtin_frame_address(0);                  //获取当前线程栈帧的 起始地址
    printf("sizeof(BigObj):%d\n", sizeof(BigObj));
    printf("stack_address:%p\n", frame_addr);
    pthread_t cur_id = pthread_self();
    pthread_attr_t attr;
    address* bottom;
    void* stack;
    size_t* size;
    size_t guard_size;

    int rslt = pthread_getattr_np(pthread_self(), &attr);
    if(rslt != 0) {
        printf("ERROR:%d\n", rslt);
        exit(EXIT_FAILURE);
    }
    pthread_attr_getguardsize(&attr, &guard_size);
    size_t stack_size;
    pthread_attr_getstacksize(&attr, &stack_size);
    char a[stack_size-10240];
    size_t size1 = (size_t)((char*)(frame_addr) - (char*)(&a[index_t]));
    BigObj a1;
    BigObj a2;
    BigObj a3;
    BigObj a4;
    BigObj a5;
    BigObj a6;
    BigObj a7;
    BigObj a8;
    BigObj a9;
    BigObj a10;
    BigObj a11;
    BigObj a12;
    BigObj a13;
    BigObj a14;

    while (true) {
        if(index_t%100 == 0) {
            printf("[%d] access address1: %p sizeof:%ld \n", index_t, &a[index_t]);
        }
        a[index_t] = 'a';
        index_t+=1;
    }
}
#define PAGE_SIZE 4096
#define STK_SIZE (10 * PAGE_SIZE)
void guard_size_thread() {
    //线程的guard区域同样是PROT_NONE的,如果访问这段内存,同样会使系统内核发出SIGSEGV信号
    signal(SIGBUS, signal_SIGBUS_handler);
//    signal(SIGSEGV, signal_SIGSEGV_handler);
    set_signal_handler(SIGSEGV);
    signal(SIGABRT, signal_SIGABRT_handler);
    signal(SIGIO, signal_SIGIO_handler);
    signal(SIGCHLD, signal_SIGCHLD_handler);

//    signal(SIGABRT, signal_SIGABRT_handler);
    size_t pagesize = sysconf(_SC_PAGESIZE);
    size_t guardsize = pagesize;
    size_t stacksize = pagesize * 8192;
    printf("pagesize:%d\n", pagesize);
    printf("sizeof(char):%d\n", sizeof(char));

    pthread_attr_t attr_t;
    pthread_t tid;
    pthread_attr_init(&attr_t);
//    pthread_attr_setstacksize(&attr_t, stacksize);
//    int ret = pthread_attr_setguardsize(&attr_t, 0);
//    printf("ret=%d\n", ret);

//    posix_memalign(&stack,PAGE_SIZE,STK_SIZE);
//    pthread_attr_setstack(&attr_t, stack, PAGE_SIZE);

//    int c;
//    std::cin >> c;

    pthread_create(&tid, &attr_t, thread_function, NULL);

    pthread_attr_getguardsize(&attr_t, &guardsize);
    pthread_attr_getstacksize(&attr_t, &stacksize);
    printf("tid=%p guardsize:%d stacksize:%d\n", pthread_self(), guardsize, stacksize);

    pthread_join(tid, NULL);

}
int main(){
  guard_size_thread();
}
rockjiang@rockjiang-virtual-machine:~/CLionProjects/test/cmake-build-debug$ ./test 
pagesize:4096
sizeof(char):1
tid=0x7fbc53ccf3c0 guardsize:4096 stacksize:8388608
ERROR ret:0
sizeof(BigObj):576
stack_address:0x7fbc53ccae50
Segmentation fault (core dumped)
rockjiang@rockjiang-virtual-machine:~/CLionProjects/test/cmake-build-debug$ ^C
  • 写回答

5条回答 默认 最新

  • Jackyin0720 2022-10-30 10:40
    关注

    提供解题思路:尝试利用gdb调试器捕获Sigsegv,或者利用core文件进行事后分析
    另外,看到你的代码有加sigsegv_handler信号的处理函数,那看一下是否可以系统调用backtrace和bacetrace_symbols打印出回溯信息。
    通过objdump 的命令将程序反汇编成一个.s的汇编文件。根据回溯信息和汇编文件的内容从而定义出产生段错误的位置。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月1日
  • 修改了问题 10月31日
  • 赞助了问题酬金20元 10月30日
  • 创建了问题 10月30日

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上