c - 如何正确设置sigaltstack?

标签 c macos signals

我已经看到至少三种不同的方法来为 sigaltstack() 设置替代堆栈。我想知道哪种方法最好:

方法#1

stack_t sigstk;
sigstk.ss_size = 0;
sigstk.ss_flags = 0;
sigstk.ss_sp = mmap (NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (sigstk.ss_sp != MAP_FAILED) {
    sigstk.ss_size = SIGSTKSZ;
    if (sigaltstack (&sigstk, 0) < 0) {
        sigstk.ss_size = 0;
        printf ("sigaltstack errno=%d\n", errno);
    }
} else {
    printf ("malloc (SIGSTKSZ) failed!\n");
}

方法#2 (我们已经使用了一段时间,但是这里分配的内存显示在泄漏检测中(leaks 命令))

stack_t sigstk;
sigstk.ss_size = 0;
sigstk.ss_flags = 0;
sigstk.ss_sp = malloc (SIGSTKSZ);
if (sigstk.ss_sp != NULL) {
    sigstk.ss_size = SIGSTKSZ;
    if (sigaltstack (&sigstk, 0) < 0) {
        sigstk.ss_size = 0;
        free (sigstk.ss_sp);
        printf ("sigaltstack errno=%d\n", errno);
    }
} else {
    printf ("malloc (SIGSTKSZ) failed!\n");
}

方法#3

stack_t sigstk;
static char ssp[SIGSTKSZ];
sigstk.ss_size = SIGSTKSZ;
sigstk.ss_flags = 0;
sigstk.ss_sp = ssp;
sigstk.ss_size = SIGSTKSZ;
if (sigaltstack (&sigstk, 0) < 0) {
    sigstk.ss_size = 0;
    free (sigstk.ss_sp);
    printf ("sigaltstack errno=%d\n", errno);
}

谢谢,阿科斯 (Mac OS X 10.8.2)

最佳答案

方法#1 是最好的。之所以是因为位置。假设您使用 #2 并且您的代码流如下所示:

void *blah = malloc (...)
...
stack_t sigstk;
sigstk.ss_size = 0;
sigstk.ss_flags = 0;
sigstk.ss_sp = malloc (SIGSTKSZ);

现在,如果您用完信号处理程序中的堆栈空间会发生什么?您的堆栈将向下增长并干扰 blah 指向的内存。如果你在某处有一些浅递归,它很容易发生。 #3 有同样的问题。

相反,使用 mmap,因为它从远离数据堆的不同池分配,并且设置保护页面是个好主意:

char* mem = mmap (NULL, 
                  SIGSTKSZ + 2*getpagesize(), 
                  PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 
                  -1, 0);
mprotect(mem, getpagesize(), PROT_NONE);
mprotect(mem + getpagesize() + SIGSTKSZ, getpagesize(), PROT_NONE);
sigstk.ss_sp = mem + getpagesize();
...

现在,如果发生堆栈溢出,您将得到一个 SIGSEGV,这比随机内存覆盖更容易调试 10 亿倍。 :)

#2 被算作泄漏的原因可能是误报。您正在使用的泄漏工具可能会用自己的变体覆盖 malloc 库函数,这是更喜欢使用 mmap 而不是 malloc< 来完成此任务的另一个原因

关于c - 如何正确设置sigaltstack?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14755341/

相关文章:

C 编程 - 为什么这个信号不被忽略?

linux - 在linux C中的特定时间发送信号

c++ - 在 xcode 中编译和链接 OpenCV 3.0.0 时遇到问题

将变量转换为它自己的类型

c - 使用 C 向 PNG 图像添加文本/注释

c - 为什么在这个例子中使用 q?

java.lang.UnsatisfiedLinkError,mach-o 但 Mac10.6.2 上的架构错误

objective-c - 确保我没有在 OSX 上使用任何不可用的 API 的最佳方法是什么?

ruby - 发送信号时运行代码,但不要在 Ruby 中捕获信号

c - 我该如何解决我的编译错误以及我应该进行哪些更改以使其改进