[C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

1. [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

M.
XProtoman

(usa Fedora)

Enviado em 05/01/2016 - 04:06h

Boa noite a todos,

Estou na dúvida se devo definir 0 para errno(errno = 0) logo após pegar o erro armazenado nessa variável.

Exemplo rápido:
int num = errno;
errno = 0;
// Faço algo com "num", para exemplificar retorno a mensagem de erro
return strerror(num);


Acabei adotando essa prática sem saber se ela é de fato correta, faço isso como forma de "limpar" o errno.

No manpages do errno:
Valid error numbers are all nonzero; errno is never set to zero by any system call or library function.


Qual a conclusão? Isso é uma prática correta?


  


2. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

Alexandre Mulatinho
mulatinho

(usa Slackware)

Enviado em 06/01/2016 - 12:25h

Acho que você entendeu um pouco errado.

A variável errno é setada automaticamente quando há um erro. Você deve validar o retorno da função e caso o retorno seja algo inesperado aí sim procurar o conteúdo da variável errno para entender especificamente o que houve. Por exemplo:

int fd, ret;

fd = open("/etc/shadow", O_RDONLY);
if (fd == -1) { // erro pq o retorno -1 do open eh um erro.
fprintf(stderr, "%d %s\n", errno, strerror(errno));
}


o errno aqui é útil para voce validar o que houve, por exemplo nesse caso se voce executou como usuário normal provavelmente voce vai receber um -EPERM (Permission denied) e voce tem como validar isso no seu código ou simplesmente imprimir o erro correto.

Então sempre que houver uma SYSCALL, o errno vai ser alterado, por isso não acho que seja uma boa prática você estar 0 no errno.


3. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

Perfil removido
removido

(usa Nenhuma)

Enviado em 06/01/2016 - 12:30h

Não seria o caso de se definir uma mensagem padronizada para cada errno?

----------------------------------------------------------------------------------------------------------------
http://24.media.tumblr.com/tumblr_m62bwpSi291qdlh1io1_250.gif

# apt-get purge systemd

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden



4. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

M.
XProtoman

(usa Fedora)

Enviado em 06/01/2016 - 14:09h

Boa tarde a todos,

Desculpem, vou deixar mas claro, o exemplo que dei foi infeliz.

Não estou ignorando o errno, na verdade eu até valorizo o seu valor o armazeno antes de limpa-lo.

Estou transformando o valor de errno em exceção(funciona bem) em C++, quando estou para terminar de fazer isso, já de posse do seu valor, limpo o errno com zero.

Não estou fazendo isso para ignorar o erro, estou fazendo isso como forma de indicar: sim o erro ocorreu, eu já o capturei(transformei em exceção), vou limpar o errno como forma de sinalizar que agora está tudo bem, afinal o próprio programa parece que começa com errno sendo 0.

A prática de limpar errno com zero está correta?

Faço isso rapidamente: pego o valor de errno e guardo em outra variável que depois será utilizada, depois limpo errno(como zero) para evitar riscos.


5. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

Enzo de Brito Ferber
EnzoFerber

(usa FreeBSD)

Enviado em 06/01/2016 - 17:59h

XProtoman escreveu:

Boa tarde a todos,

Desculpem, vou deixar mas claro, o exemplo que dei foi infeliz.

Não estou ignorando o errno, na verdade eu até valorizo o seu valor o armazeno antes de limpa-lo.

Estou transformando o valor de errno em exceção(funciona bem) em C++, quando estou para terminar de fazer isso, já de posse do seu valor, limpo o errno com zero.

Não estou fazendo isso para ignorar o erro, estou fazendo isso como forma de indicar: sim o erro ocorreu, eu já o capturei(transformei em exceção), vou limpar o errno como forma de sinalizar que agora está tudo bem, afinal o próprio programa parece que começa com errno sendo 0.

A prática de limpar errno com zero está correta?

Faço isso rapidamente: pego o valor de errno e guardo em outra variável que depois será utilizada, depois limpo errno(como zero) para evitar riscos.


Olá,


Faço isso rapidamente: pego o valor de errno e guardo em outra variável que depois será utilizada, depois limpo errno(como zero) para evitar riscos.


Como assim "evitar riscos"? Quais riscos?
Você está usando a variavél errno "pessoalmente" (no seu programa)?

Do manual de perror (a função usada para traduzir as mensagens de erro): [http://linux.die.net/man/3/perror]

(..)
When a system call fails, it usually returns -1 and sets the variable errno to a value describing what went wrong. (These values can be found in <errno.h>.) Many library functions do likewise. The function perror() serves to translate this error code into human-readable form. Note that errno is undefined after a successful library call: this call may well change this variable, even though it succeeds, for example because it internally used some other library function that failed. Thus, if a failing call is not immediately followed by a call to perror(), the value of errno should be saved.
(...)


Explicitamente dito que o valor dela após a chamada a perror é indefinido. Portanto, nem o wrapper da libc limpa a errno, porque você iria querer fazer isso?
Não entendi...

Atenciosamente,
Enzo Ferber
[]'s


$ cat codigo.c | indent -kr -i8
$ man indent

"(...)all right-thinking people know that (a) K&R are _right_ and (b) K&R are right." - linux/Documentation/CodingStyle - TORVALDS, Linus.



6. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

Paulo
paulo1205

(usa Ubuntu)

Enviado em 06/01/2016 - 21:45h

Não existe necessidade de resetar errno depois de pegar seu valor. O que muitas vezes se faz é justamente o contrário: resetá-lo antes de chamar uma função que possa gerar erro, para ter certeza de que erro veio dessa função especificamente, e não de alguma outra operação anterior. Isso é particularmente necessário com funções que não têm como sinalizar erro explicitamente e inequivocamente (por exemplo: strtol() é sujeita a erros de overflow ou underflow, podendo setar errno com ERANGE nesses casos, só que os valores devolvidos pela conversão nesses mesmos casos seriam indistinguíveis de conversões válidas de LONG_MAX e LONG_MIN, respectivamente).


7. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

M.
XProtoman

(usa Fedora)

Enviado em 07/01/2016 - 17:44h

[EDIT]

Sobre "porque você iria querer fazer isso?": estou trabalhando com C++ e transformando os erros de algumas funções que preciso utilizar de C em exceções(exception), então depois que pego o valor de errno penso em sinalizar que está tudo "ok" e limpo defino errno com 0.

É uma biblioteca em C++, tem várias coisas de C que preciso, mas deixo o programador trabalhar com coisas de C++, como Orientação a Objeto, Exceções, em vez de se preocupar com o errno, por isso até o interesse de pós tratamento defini-lo como 0.

paulo1205 obrigado, não conheço bem o strtol, mas essa questão que o senhor apresentou é interessante.

Acho que com essas respostas talvez o que esteja fazendo não comprometa muita coisa a não ser desempenho* ou o desejo do programador de pegar o código e a mensagem de erro do errno, porém ambos(código e mensagem) eu repasso ao programador se ele desejar saber, então não estou ignorando nenhum erro, nem impedindo ninguém de saber o valor de errno. Refletindo as respostas e imaginando como errno trabalha, seta-lo para zero pós tratamento não trás problemas.

* = nem considero isso porque tem que ser muito unha de fome em desempenho.


8. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/01/2016 - 01:00h

XProtoman escreveu:

então vamos supor que um programador faça algo assim:
socket(...)
connect(...)
// Se socket() deu erro checar AGORA o valor de errno.


Você já viu alguém fazendo desse jeito? Só se for alguém muito preguiçoso.

Por que todo mundo evita isso e não faz desse jeito?


Não entendi. Você estava preocupado com que alguém fizesse isso, e agora diz que todo mundo evita?

Porque connect() pode também ter alterado o valor de errno se também deu erro.


Não é esse o motivo. O real motivo é que se socket() falhar -- independentemente da causa refletida no valor de errno --, não fará sentido nenhum tentar chamar connect(), pois não haverá um socket válido sobre o qual se possa tentar realizar uma conexão. Se você insistir com a chamada a connect() com o socket inválido, já saberá de antemão que ela vai retornar falha e vai setar errno com EBADF.

Por que o cara não fez:
socket(...)
// Se socket() deu erro checar o valor de errno.
connect(...)
// Se connect() deu erro checar o valor de errno.

Bom é esse tipo de risco que busco evitar que a maioria também evita.


Não quero ser chato, mas não consigo ver como interferir no valor de errno entre uma chamada e outra pode lhe ajudar. Você temia a perda acidental do valor, e propõe como solução a perda proposital desse valor. Não faz muito sentido para mim.

Sobre "porque você iria querer fazer isso?": estou trabalhando com C++ e transformando os erros de algumas funções que preciso utilizar de C em exceções(exception), então depois que pego o valor de errno penso em sinalizar que está tudo "ok" e limpo defino errno com 0.


Se você está criando uma biblioteca, sugiro que pondere sobre algumas escolhas.

Uma biblioteca, de modo geral, deve ser minimamente intrusiva sobre variáveis globais que possam ser utilizadas oor outras partes do programa. Então, se você não pretende usar errno para indicar um erro, não impeça outra função ou biblioteca de o fazer (a não ser que você tenha sólidas razões para esconder a real causa do erro).

Outra consideração deve ser sobre o próprio mecanismo de exceções para sinalização de erros. Se você vai simplesmente envelopar errno na forma throw std::runtime_error(strerror(errno));, vai usar um mecanismo pesado sem agregar realmente muita informação.


9. Re: [C/C++] Dúvida sobre prática de programação de definir 0 para errno(errno = 0)

M.
XProtoman

(usa Fedora)

Enviado em 08/01/2016 - 03:13h

Boa noite a todos e obrigado mais uma vez a vocês,

Sobre meu post anterior sabia que iria gerar problemas, a direção mesmo é o lance de definir errno com 0.

Sobre o exemplo com socket() e connect(), foi uma resposta a Enzo: O que eu quis dizer é que alguém programando em C, que não tem nada haver com a biblioteca nem faz uso dela no seu exercício de programação nem também tem nada haver com errno = 0, por inexperiência, poderia chamar duas funções qualquer que definem errno e só depois de chamar a segunda iria checar o errno esperando que ele tivesse o resultado da primeira.

Você paulo1205 foi direto ao ponto que é a questão de definir errno com 0, mas surgiu a pergunta de EnzoFerber e achei precisava responder(respondi antes), achei que talvez fosse gerar repercussão e fugir do errno = 0, mas acabei decidindo continuar e postei, mas me arrependo, para evitar problemas estou editando o post anterior removendo a parte polêmica referente ao exemplo.

Paulo1205 sobre o que você falou agora no final, criei uma exceção que armazena e pode entregar ao utilizador tanto o valor que foi dado pelo errno quanto a mensagem de erro correspondente.

Antes fazia algo similar ao que você mostrou(throw std::runtime_error(strerror(errno));), mas em Sockets precisei realmente saber o valor de errno e não só a mensagem, por isso a exceção passou a abrigar também o valor de errno, por enquanto está atendendo.

Se fosse C puro talvez não fizesse errno = 0, mas como é C++ e tem exceções quero que o programador trabalhe com elas.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts