Возвратитесь из вычислительного обработчика сигнала исключения

Неопределенное поведение, когда обработчик сигнала обычно возвращается из ошибки в программе

Описание

Возвратитесь из вычислительного обработчика сигнала исключения, происходит, когда обработчик сигнала возвращает после ловли вычислительного сигнала исключения SIGFPE, SIGILL или SIGSEGV.

Риск

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

Фиксация

Проверяйте валидность значений ваших переменных перед вычислением, чтобы избегать использования обработчика сигнала, чтобы отловить исключения. Если вы не можете избежать обработчика, чтобы отловить сигналы исключения вычисления, вызовите abort(), quick_exit() или _Exit() в обработчике, чтобы остановить программу.

Примеры

развернуть все

#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>

static volatile sig_atomic_t denom;
/* Declare signal handler to catch division by zero 
computation error. */
void sig_handler(int s)
{
    int s0 = s;
    if (denom == 0)
    {
        denom = 1;
    }
	/* Normal return from computation exception
	signal */
    return; 
}


long func(int v)
{
    denom = (sig_atomic_t)v;
       
        if (signal(SIGFPE, sig_handler) == SIG_ERR)
        {
            /* Handle error */
        }
		
	long result = 100 / (long)denom;
    return result;
}
        
      

В этом примере sig_handler, как объявляют, обрабатывает ошибку вычисления деления на нуль. Обработчик изменяет значение denom, если это - нуль и возвращается, который является неопределенным поведением.

Исправление — вызывает abort(), чтобы отключить программу

После ловли вычислительного исключения вызовите abort() от sig_handler, чтобы выйти из программы без дальнейшей ошибки.

#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>

static volatile sig_atomic_t denom;
/* Declare signal handler to catch division by zero 
computation error. */

void sig_handler(int s)
{
    int s0 = s;
	/* call to abort() to exit the program */
    abort(); 
}

long func(int v)
{
    denom = (sig_atomic_t)v;
       
        if (signal(SIGFPE, sig_handler) == SIG_ERR)
        {
            /* Handle error */
        }
		
	long result = 100 / (long)denom;
    return result;
} 

Информация о результате

Группа: Программирование
Язык: C | C++
Значение по умолчанию: на
Синтаксис командной строки: SIG_HANDLER_COMP_EXCP_RETURN
Влияние: низко
ID CWE: 387

Введенный в R2017b