[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

3 Controlando Erro

O presente capítulo descreve a forma que funções GSL relatam e controlam erros. Por meio do exame à informação de situação atual retornada por toda função você pode determinar se a função obteve sucesso ou falhou, e se a função tiver falhado você pode encontrar qual foi a precisa causa da falha. Você pode também definir suas próprias funções de controle de erros para modificar o comportamento padrão da biblioteca.

As funções descritas nessa seção são declaradas no arquivo de cabeçalho ‘gsl_errno.h’.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

3.1 Relatórios de Erro

A biblioteca segue as convenções de relato de erro para linhas de execução segura da biblioteca de linha de execução POSIX. Funções retornam um código de erro diferente de zero para indicar um erro e 0 para indicar sucesso.

int status = gsl_function (...)

if (status) { /* an error occurred */
  .....       
  /* status value specifies the type of error */
}

As rotinas reportam um erro sempre que elas não puderem executar a tarefa requisitada delas. Por exemplo, uma função de busca por uma raíz pode retornar um código de erro diferente de zero se não puder convergir com a exatidão requisitada, ou exceder um limite numérico de repetições. Situações como essas são uma ocorrência normal quando usamos qualquer biblioteca matemática e você deve verificar a situação atual do retorno de funções que você chama.

sempre que uma rotina informar um erro o valor de retorno especifica o tipo de erro. O valor de retorno é semelhante ao valor da variável errno na biblioteca C. Quem fez a chamada pode examinar o código de retorno e decidir que ação executar, inclusive ignorando o erro se esse erro não for considerado grave.

Adicionalmente para informar erros por meio do código de retorno a biblioteca também tem uma função de controle de erro chamada gsl_error. Essa função é chamada por outras funções de biblioteca quando elas informam um erro, somente antes dessas outras funções retornarem à função chamadora. O comportamento padrão do controlador de erro é mostrar uma mensagem e interromper o programa,

gsl: file.c:67: ERROR: invalid argument supplied by user
Default GSL error handler invoked.
Aborted

O objetivo do controlador gsl_error é fornecer uma função onde um ponto de parada possa ser ajustado o qual irá capturar erros de biblioteca quando executando dentro de um depurador de erros. A função controladora de erro não foi pensada para ser usada em programas de produção, os quais devem controlar quaisquer erros usando os códigos de retorno.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

3.2 Códigos de Erro

Os códigos de erros numéricos retornados através das funções de biblioteca são definidos no arquivo ‘gsl_errno.h’. Todos os códigos de erro possuem o prefixo GSL_ e expandem para valores inteiros do tipo constante e são diferentes de zero. códigos de erros acima de 1024 são reservados para aplicações, e não são usados pela biblioteca. Muitos dos códigos de erro usam o mesmo nome básico do correspondente código de erro na biblioteca C. Aqui estão alguns dos códigos de erro mais comuns,

Macro: int GSL_EDOM

Erro de domínio; usado por funções matemáticas quando um valor de argumento está fora domínio sobre o qual a função que está sendo usada está definida (da mesma forma que EDOM na biblioteca C)

Macro: int GSL_ERANGE

Erro de intevalo; usado pr funções matemáticas quando o valor do resultado não é representável pelo fato de muito grande ou muito pequeno (da mesma forma que ERANGE na biblioteca C)

Macro: int GSL_ENOMEM

Sem memória disponível. O sistema não pode alocar mais memória virtual pelo fato de sua capacidade ter sido toda usada (da mesma forma que ENOMEM na biblioteca C). esse erro é informado quando a rotina GSL encontra problemas ao tentar alocar memória com malloc.

Macro: int GSL_EINVAL

Argumento inválido. É usada para indicar vários tipos de problema com a informação de argumentos inadequados enviados a uma função de biblioteca (da mesma forma que EINVAL na biblioteca C library).

Os códigos de erro podem ser convertidos em uma mensagem de erro usando a função gsl_strerror.

Function: const char * gsl_strerror (const int gsl_errno)

Essa função retorna um apontador para uma sequência de caracteres descrevendo o código de erro gsl_errno. Por exemplo,

printf ("erro: %s\n", gsl_strerror (status));

não irá mostrar uma mensagem de erro com erro: erro de intervalo de saída para um valor de situação atual de GSL_ERANGE.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

3.3 Controladores de Erro

O comportamento padrão do controlador de erro da GSL é mostrar uma mensagem curta e chamar abort. Quando esse comportamento padrão for adotado por um programa que estiver sendo usado irá parar o programa criando um arquivo core-dump mesmo se uma rotina de biblioteca informar um erro. O objetivo desse comportamento é ser um padrão de erro seguro para programas que não verificam a situação atual de retorno de rotinas de biblioteca (não encorajamos você a escrever programas dessa forma).

Se você desabilitar o controlador de erro padrão a responsabilidade é toda e exclusivamente sua de verificar os valores de retorno de rotinas e manipulá-los você mesmo. você pode também personalizar o comportamento de erro fornecendo um novo controlador de erro. Por exemplo, um controlador de erro alternativo pode gravar em um arquivo, ignorar certas condições de erro (tais como valores muito pequenos), ou iniciar o depurador e anexar o depurador ao processo atual quando um erro ocorrer.

Todos os controladores de erro da GSL possuem o tipo gsl_error_handler_t, o qual é definido em ‘gsl_errno.h’,

Tipo de Dados: gsl_error_handler_t

Esse é o tipo das funções controladoras de erro da GSL. Ao controlador de erro irá ser informado quatro argumentos os quais especificam a razão para o erro (uma sequência de caracteres), o nome do arquivo fonte no qual o erro ocorreu (também uma sequência de caracteres), o número da linha daquele arquivo (um inteiro) e o número do erro (um inteiro). O arquivo fonte e o número de linha são ajustados na hora da compilação usando as diretivas __FILE__ e __LINE__ no pré-processador. Uma função controladora de erro retorna o tipo de dado void. Funções controladoras de erro devem ser definidas como segue,

void handler (const char * reason, 
              const char * file, 
              int line, 
              int gsl_errno)

Para requisitar o uso de seu próprio controlador de erro você precisa chamar a função gsl_set_error_handler a qual é também declarada em ‘gsl_errno.h’,

Function: gsl_error_handler_t * gsl_set_error_handler (gsl_error_handler_t * new_handler)

Essa função ajusta um novo controlador de erro, new_handler, para as rotinas de biblioteca da GSL. O controlador antigo é guardado em memória (de forma que você pode recuperá-lo mais tarde). Note que o apontador para uma função controladora de erro definida pelo usuário é armazenado em uma variável estática, de forma que existe um único controlador de erro por programa. Essa função não deve ser usada em programas com suporte a múltiplas linhas de execução exceto para ajustar um controlador de erro que abrange completamente um programa a partir de uma linha de execução principal. O exemplo seguinte mostra como ajustar e retaurar um novo controlador de erro,

/* grava o controlador original, instala um novo controlador */
old_handler = gsl_set_error_handler (&my_handler); 

/* o código uso o novo controlador */
.....     

/* restaura o controlador original */
gsl_set_error_handler (old_handler); 

Para usar o comportamento padrão (abort em caso de erro) ajuste o controlador de erro para NULL,

old_handler = gsl_set_error_handler (NULL); 
Function: gsl_error_handler_t * gsl_set_error_handler_off ()

Essa função desabilita o controlador de erro por meio da definição de um controlador de erro que não faz nada. Isso irá fazer com que o programa continue após qualquer erro, de forma que o valor de retorno de qualquer rotina de biblioteca da GSL deva ser verificado. Esse é o comportamento recomendado para programas de produção. O controlador antigo é guardado em memória (de forma que você pode restaurar o controlador antigo posteriormente).

O comportamento de erro pode ser mudado para aplicações específicas através da recompilação da biblioteca com uma definição personalizada da macro GSL_ERROR no arquivo ‘gsl_errno.h’.


[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

3.4 Usando relatório de erro da GSL em suas próprias funções

Se você está escrevendo funções numéricas em um programa que também usa código da GSL você pode achar conveniente adotar as mesmas conveções de relatório de erros adotadas pela biblioteca GSL.

Para informar um erro você precisa chamar a função gsl_error com uma sequência de caracteres descrevendo o erro e então retornar um código de erro apropriado a partir de gsl_errno.h, ou um valor especial, tal com NaN. Por conveniencia o arquivo ‘gsl_errno.h’ define duas macros que realizam esses passos:

Macro: GSL_ERROR (reason, gsl_errno)

Essa macro informa um erro usando as convenções da GSL e retorna um valor da situação atual de gsl_errno. Expande para o seguinte fragmento de código,

gsl_error (reason, __FILE__, __LINE__, gsl_errno);
return gsl_errno;

A definição de macro em ‘gsl_errno.h’ atualmente abrange o código em um bloco do { ... } while (0) para prevenir possíveis problemas de valores de retorno.

Aqui está um exemplo de como a macro pode ser usada para informar que uma rotina não encontrou uma tolerância requisitada. Para informar o erro a rotina precisa retornar o código de erro GSL_ETOL.

if (residual > tolerancia) 
  {
    GSL_ERROR("residual excede tolerancia", GSL_ETOL);
  }
Macro: GSL_ERROR_VAL (reason, gsl_errno, valor)

Essa macro é a mesma que GSL_ERROR mas retorna um valor definido pelo usuário armazenado em valor ao invés de um código de erro. GSL_ERROR_VAL pode ser usada para funções matemáticas que retornam um valor em ponto flutuante.

O seguinte exemplo mostra como retornar um NaN em uma singularidade matemática usando a macro GSL_ERROR_VAL,

if (x == 0) 
  {
    GSL_ERROR_VAL("o argumento localiza-se em uma singularidade", 
                  GSL_ERANGE, GSL_NAN);
  }

[ << ] [ < ] [ Acima ] [ > ] [ >> ]         [Topo] [Conteúdo] [Índice] [ ? ]

3.5 Exemplos

Aqui está um exemplo de algum código que verifica o valor de retorno de uma função onde um erro pode ser informado,

#include <stdio.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_fft_complex.h>

...
  int status;
  size_t n = 37;

  gsl_set_error_handler_off();

  status = gsl_fft_complex_radix2_forward (data, stride, n);

  if (status) {
    if (status == GSL_EINVAL) {
       fprintf (stderr, "argumento invalido, n=%d\n", n);
    } else {
       fprintf (stderr, "falhou, gsl_errno=%d\n", 
                        status);
    }
    exit (-1);
  }
...

A função gsl_fft_complex_radix2 somente aceita comprimentos de inteiros que são uma potência de dois. Se a variável n não for uma potência de dois então a chamada para a função de biblioteca irá retornar GSL_EINVAL, indicando que o comprimento do argumento é inválido. A chamada de função a gsl_set_error_handler_off impede o controlador de erro padrão de abortar o programa. A cláusula else captura quaisquer outros erros possíveis.


[ << ] [ >> ]           [Topo] [Conteúdo] [Índice] [ ? ]

Esse documento foi gerado em 23 de Julho de 2013 usando texi2html 5.0.