Clique sobre os tópicos listados abaixo para navegar até o conteúdo desejado.

  1. Sinais
  2. Lançando sinal
  3. Tratamento padrão e ignorar sinal
  4. Tratamento customizado

Sinais(Signals), de forma básica, são interrupções geradas por nossos programas que são passados para o sistema operacional. A linguagem C suporta os sinais abaixo:

Sinais
1 SIGFPE(Signal Floating-Point Exception) Erro em operação aritmética
2 SIGSEGV(Signal Segmentation Violation) Violação de acesso à memória.
3 SIGILL(Signal Illegal Instruction) Instrução inválida
4 SIGABRT(Signal Abort) Abortar programa
5 SIGINT(Signal Interrupt) Interrupção de software. Ctrl + C/X
6 SIGTERM(Signal Terminate) Término de execução. Sem erros

O S.O possui funções previamente definidas para para tratamento de cada sinal listado acima. Esses sinais podem ser ignorados, tratados de forma customizada ou o tratamento padrão.

Para utilizar as constantes e funções para lidar sinais, é necessário incluir a biblioteca signals:

Sintaxe: include
#include <signal.h>

Para lançar um um sinal ou interrupção, utilizamos a função raise de acordo com a sintaxe mostrada abaixo:

Sintaxe: include
int raise(int sig)
Sintaxe:
sig: sinal para lançar: 0~6 ou customizado.
Retorno
0: sucesso
outro: falha
Exemplo 1
#include <signal.h> 

int main()
{
   raise(SIGINT); //terminar com ctrl-c
   //raise(SIGTERM); //terminar
   //raise(SIGABRT); //abortar
   return 0;
}
Saída
- 

Caso seja necessário ignorar um sinal, utilizamos a função signal como mostrado na próxima sintaxe:

Sintaxe: include
signal(SINAL,SIG_IGN)
Onde
SINAL: sinal para ignorar
SIG_IGN: valor para ignorar sinal
Exemplo 2
#include <stdio.h> 
#include <signal.h> 
   
   
int main()  
{ 
    int var_int = 0;
    signal(SIGINT, SIG_IGN); //ignora ctrl-c
    while(1)
    {
        printf("entre com um número: ");
        scanf("%d",&var_int);
        if(var_int == 999)
            break;
    }
    return 0; 
}
Entrada
ctrl+c
100
10
ctrl+c
999
Entrada
entre com um número: ^C100
entre com um número: 10
entre com um número: ^C999

O tratamento padrão é definido utilizando o valor SIG_DFL como argumento da função signal como mostrado na sintaxe a seguir:

Sintaxe: include
signal(SINAL, SIG_DFL);
Exemplo 3
#include <stdio.h> 
#include <signal.h> 
   
   
int main()  
{ 
    int var_int = 0;
    signal(SIGINT, SIG_IGN); //ignora ctrl-c
    while(1)
    {
        printf("entre com um número: ");
        scanf("%d",&var_int);
        if(var_int == 999)
            break;
    }
    return 0; 
}
Entrada
ctrl+c
Saída
entre com um número: ^C

De acordo com a situação em que nosso programa se encontra: erro, validação ou outro, o tratamento do sinal pode ser utilizado para liberar recursos alocados.

Sintaxe: signal
void (*signal(int sig, void (*func)(int)))(int)
Onde
func: função callback de tratamento
sig: sinal para tratamento
Retorno
-
Exemplo 4: SIGINT com tratamento
#include <stdio.h> 
#include <signal.h> 
  
void ctrl_c(int sig)  { 
    printf("ctrl-c ignorado!\n"); 
} 
  
int main()  { 
    signal(SIGINT, ctrl_c); 
    for(;;);
    return 0; 
}
Entrada
ctrl+c
Saída
^Cctrl-c ignorado!
Exemplo 5: SIGTERM
#include <stdio.h> 
#include <signal.h> 
  
void tratamento(int sig)  { 
    printf("parâmetro invalido");
    exit(1) //atexit se registrada
} 
  
int main()  
{ 
    signal(SIGTERM, tratamento); 
    //signal(SIGABRT,tratamento);
    int a = 0;
    
    if(a == 0){
        raise(SIGTERM);
        //raise(SIGABRT);
    }
    
    return 0; 
}
Saída
parâmetro invalido

No próximo exemplo, vamos utilizar um ponteiro não iniciado para atribuição indireta de um valor. Isso irá gerar, implicitamente, um sinal SIGSEGV que será capturado em uma função de tratamento configurada pela função signal.

Exemplo 6: Violação de memória
#include <stdio.h> 
#include <signal.h> 
  
void tratamento(int sig)  { 
    printf("SIGSEGV! detectado!\n"); 
    //tratamento
    raise(SIGABRT);
} 
  
int main()  
{ 
    int var_int = 0;
    
    signal(SIGSEGV, tratamento); //registra SIGSEGV
    
    int *ponteiro1 = NULL, 
        *ponteiro2 = NULL;
        
    ponteiro2 = &var_int;
    
    *ponteiro2 = 0xffffffff;
    *ponteiro1 = 0xffffffff; //violação de acesso SIGSEGV
    return 0; 
}
Saída
SIGSEGV detectado!

Os sinais e seus tratamentos podem ser utilizados em conjunto com as funções exit ou atexit para uma melhor organização de tratamento de erros ao encerrar um programa utilizando SIGTERM e SIGABRT, por exemplo.

  1. 05/05/2025 - versão inicial