捕捉细分违规行为并继续生活 [英] Catching Segmentation Violations and Getting on with Life

查看:42
本文介绍了捕捉细分违规行为并继续生活的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个检查其自身地址空间的程序.

I'm writing a program that's examining its own address space.

具体来说,我关心所有malloc分配的数据块.如果有一些系统调用来获取它们的列表,那就太好了(对于我的应用程序,我不能使用LD_PRELOAD,-wrap或任何其他命令行选项).如果有办法做到这一点,我很想听听它,而不仅仅是在下面对我陈述的问题的答案.

Specifically, I care about all malloc-ed data blocks. If there some system call to get a list of them, that would be fantastic (for my application, I cannot use LD_PRELOAD, -wrap, nor any extra command line options). If there's a way to do this, I'd love to hear it even more than an answer to my stated problem, below.

代替此,我当前的方法是仅取消引用所有内容并环顾四周.显然,所有可能的指针的集合都是等待发生段错误的雷区,因此我尝试注册信号处理程序并使用setjmp/longjmp(通过使处理程序不执行任何操作来忽略段错误都是无限循环,因为处理程序将返回到错误的指令).一些示例代码如下:

In lieu of this, my current approach is to just dereference everything and look around. Obviously, the set of all possible pointers is a minefield of segfaults waiting to happen, so I tried registering a signal handler and using setjmp/longjmp (simply ignoring the segfault by making the handler do nothing is an infinite loop because the handler will return to the faulting instruction). Some example code goes like so:

static jmp_buf buf;
void handler(int i) {
    printf("    Segfaulted!\n");
    longjmp(buf,-1);
}
void segfault(void) {
    int* x = 0x0;
    int y = *x;
}
void test_function(void) {
    signal(11,handler);
    while (1) {
        if (setjmp(buf)==0) {
            printf("Segfaulting:\n");
            segfault();
        }
        else {
            printf("Recovered and not segfaulting!\n");
        }
        printf("\n");
    }
}

输出为:

    Segfaulting:
        Segfaulted!
    Recovered and not segfaulting!

    Segfaulting:
    Segmentation fault

因此,处理程序第二次没有工作.我不知道为什么,但是我推测这与不清除原始信号有关.我不知道该怎么办.

So, the handler didn't work the second time around. I don't know why this is, but I speculated it had something to do with not clearing the original signal. I don't know how to do that.

顺便说一句,我首先尝试了sigsetjmp/siglongjmp,但是由于某种原因在setjmp.h中未对其进行定义.我有一个模糊的共鸣,认为需要传递一些额外的编译标志,但是像以前一样,此应用程序不允许这样做.

As an aside, I tried sigsetjmp/siglongjmp first, but they weren't defined for some reason in setjmp.h. I got vague vibes that one needed to pass some extra compile flags, but, as before, that is not allowed for this application.

正在使用的系统是Ubuntu Linux 10.04 x86-64,并且 都不需要任何解决方案.

The system being used is Ubuntu Linux 10.04 x86-64, and any solution does not need to be portable.

谢谢!
伊恩[

Thanks!
Ian[

处理程序中的sigrelse清除信号,并有效解决问题.现在的问题与提出的其他问题有关-是否有更好的方法(即获取malloc的块)? sigsetjmp/siglongjmp怎么了?为什么我需要重置信号?]

sigrelse in the handler clears the signal, and fixes the problem effectively. Question now concerns the other issues raised--is there a better way (i.e., get the blocks of malloc)? What's up with sigsetjmp/siglongjmp? Why do I need to reset the signal?]

推荐答案

当调用SIGSEGV的信号处理程序时,SIGSEGV信号将被sigprocmask屏蔽.对于任何信号都是如此.通常,从信号处理程序返回将取消屏蔽它,但是由于您不返回,因此永远不会发生.有两种可能的解决方案:

When the signal handler for SIGSEGV is invoked, the SIGSEGV signal will be masked as if by sigprocmask. This is true for any signal. Normally returning from the signal handler would unmask it, but since you're not returning, that never happens. There are a couple possible solutions:

  • 您可以在longjmp之前或之后致电sigprocmask自己取消屏蔽.
  • 您可以使用sigaction(无论如何首选的方式)安装信号处理程序,并使用SA_NODEFER标志来防止其被屏蔽.
  • 您可以使用sigsetjmpsiglongjmp函数,它们自己负责保存和恢复信号掩码.
  • You can call sigprocmask either before or after the longjmp to unmask it yourself.
  • You can install the signal handler with sigaction (the preferred way to do it anyway) and use the SA_NODEFER flag to prevent it from being masked.
  • You can use the sigsetjmp and siglongjmp functions, which themselves take responsibility for saving and restoring the signal mask.

这篇关于捕捉细分违规行为并继续生活的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆