exponenta event banner

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

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

Описание

Этот дефект возникает, когда обработчик сигнала возвращается после захвата сигнала вычислительного исключения 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
Воздействие: Низкий
ИДЕНТИФИКАТОР CWE : 387
Представлен в R2017b