Ошибка сегментации в обработчике ошибок сегментации - PullRequest
0 голосов
/ 08 июня 2018

Я столкнулся с проблемой, при которой ошибка сегментации возникает в обработчике ошибок сегментации.Хотя я уже исправил реальную проблему, но все же меня смущает то, что нижеприведенная программа не работает в бесконечном цикле:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void C() 
{
    int *p = NULL;
    *p = 3;
}

void B() 
{
    C();
}

void segfault_sigaction(int signal, siginfo_t *si, void *arg)
{
    printf("Came in sigaction.\n");
    //if(si)
        //printf("Caught segfault at address %p\n", si->si_addr);
    B();
}
int main(void)
{
    struct sigaction sa; 

    memset(&sa, 0, sizeof(struct sigaction));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = segfault_sigaction;
    sa.sa_flags   = SA_SIGINFO;

    sigaction(SIGSEGV, &sa, NULL);

    segfault_sigaction(0, NULL, NULL);

    return 0;
}

Вывод приведенного выше кода выглядит следующим образом:

Came in sigaction.
Came in sigaction.
Segmentation fault (core dumped)

В комментариях к подобному посту: Ошибка сегментации в обработчике ошибок сегментации некоторые люди отметили, что она должна идти в бесконечном цикле, но это не текущее поведение.Может кто-нибудь объяснить мне, что происходит ??

1 Ответ

0 голосов
/ 08 июня 2018

Вы поднимаете сигнал, находясь в обработчике сигнала.Стандарт POSIX гласит: :

[таблица безопасных функций]

Все функции, не указанные в приведенной выше таблице, считаются небезопаснымипо отношению к сигналам.При наличии сигналов все функции, определенные этим томом стандарта IEEE Std 1003.1-2001, должны вести себя так, как определено при вызове или прерывании функцией перехвата сигнала, с одним исключением: , когда сигнал прерывает небезопасную функцию ифункция перехвата сигнала вызывает небезопасную функцию , поведение не определено.

void C() является небезопасной функцией, поскольку ее нет в списке безопасных функций, поэтому ее вызовсигнал вызывает неопределенное поведение.(Я думаю, это также означает, что повышение сигнала от функции-обработчика сигнала также вызывает UB, хотя формулировка неясна).

Будучи неопределенным поведением, вы не можете полагаться на бесконечный цикл или любой другой такойповедение.

Другие пункты:

  • Разыменование null является неопределенным поведением и не гарантирует генерацию SIGSEGV в первую очередь.
  • Вызов printf в обработчике сигналаявляется неопределенным поведением, потому что это также не является одной из безопасных функций из таблицы.
  • Это также UB, чтобы вернуться из обработчика сигнала для SIGSEGV.Единственный переносимый способ выйти из обработчика сигнала - это прервать процесс с помощью вызова, такого как exit.
...