Quando devo usar perror (“…”) e fprintf (stderr, “…”)?

105

Ler as páginas do manual e algum código não me ajudou muito a entender a diferença entre - ou melhor, quando devo usar - perror("...")ou fprintf(stderr, "...").

freeboy1015
fonte

Respostas:

113

Chamar perrorfornecerá o valor interpretado de errno, que é um valor de erro local de thread gravado por syscalls POSIX (ou seja, cada thread tem seu próprio valor para errno). Por exemplo, se você fez uma chamada para open(), e um erro foi gerado (ou seja, ele retornou -1), você poderia ligar perrorimediatamente depois para ver qual era o erro real. Lembre-se de que, se você chamar outras syscalls nesse ínterim, o valor em errnoserá sobrescrito e a chamada perrornão terá nenhuma utilidade para diagnosticar seu problema se um erro tiver sido gerado por uma syscall anterior.

fprintf(stderr, ...)por outro lado, pode ser usado para imprimir suas próprias mensagens de erro personalizadas. Ao imprimir para stderr, você evita que a saída do relatório de erros seja misturada com a saída "normal" que deveria estar stdout.

Lembre-se de que fprintf(stderr, "%s\n", strerror(errno))é semelhante a perror(NULL)porque uma chamada para strerror(errno)gerará o valor da string impressa para errnoe você pode então combiná-lo com qualquer outra mensagem de erro personalizada via fprintf.

Jason
fonte
3
Ah, entendi. A função perror funciona de maneira diferente dependendo do valor de errno. If you use a function that effects errno then it makes sense to use perror.Se você usar uma função que não afeta errno e simplesmente retorna um código de erro, você deve usar fprintf (stderr, fmt, ...). Por exemplo, strtol retornará LONG_MAX ou LONG_MIN se uma string estiver fora do intervalo e definir errno como ERANGE. Portanto, se strtol falhar devido a estar fora do intervalo, eu usaria perror.
freeboy1015
6
Um detalhe, strerrornão precisa ser thread-safe. É estúpido, mas esse é o padrão. strerror_lpode ser usado como substituto imediato nos sistemas POSIX 2008. strerror_rtambém está disponível em sistemas mais antigos, mas tem problemas realmente desagradáveis ​​com alguns sistemas que possuem versões não conformes.
R .. GitHub PARAR DE AJUDAR O ICE
também como um detalhamento, acho que perroracrescenta '\n'no final então o formato ficaria "%s\n", não?
Jens Gustedt
1
@R .., ha, eu já paguei, e pelo que sei eles não estão me pagando nada. E como a MS parece estar cortando completamente o suporte para C, no final eu serei o único :) strerror_sna verdade não é tão ruim como interface.
Jens Gustedt
2
Cortando o suporte completamente? Parece que enganaram o comitê novamente. Colocar seu _slixo no padrão foi basicamente um jogo da MS ("Se você adotar nossas interfaces, consideraremos realmente fazer nossos produtos suportarem seu padrão.") E é claro que agora eles não estão seguindo adiante. Na verdade, concordo que essa interface não é ruim em si mesma. O que é ruim é a propaganda (na forma de avisos do compilador) de que a maior parte da biblioteca padrão é "insegura" e que toda a família de _sfunções deve ser usada em vez das padrão.
R .. GitHub PARAR DE AJUDAR O ICE
40

Eles fazem coisas bem diferentes.

Você usa perror()para imprimir uma mensagem stderrque corresponda a errno. Você usa fprintf()para imprimir qualquer coisa para stderr, ou qualquer outro fluxo. perror()é uma função de impressão muito especializada:

perror(str);

é equivalente a

if (str)
    fprintf(stderr, "%s: %s\n", str, strerror(errno));
else
    fprintf(stderr, "%s\n", strerror(errno));
freeboy1015
fonte
12

perror(const char *s): imprime a string fornecida seguida por uma string que descreve o valor atual de errno.

stderr: é um fluxo de saída usado para enviar suas próprias mensagens de erro (o padrão é o terminal).

Relevante:

char *strerror(int errnum): dê a ele um número de erro e ele retornará a string de erro associada.

Adib Saad
fonte
2

perror () sempre escreve em stderr; strerr (), usado junto com fprintf (), pode escrever em qualquer saída - incluindo stderr, mas não exclusivamente.

fprintf(stdout, "Error: %s", strerror(errno));
fprintf(stderr, "Error: %s", strerror(errno)); // which is equivalent to perror("Error")

Além disso, perror impõe sua própria formatação de texto "texto: descrição do erro"

Sebastien
fonte
-2

A função Perror leva mais tempo para realizar a chamada de execução vai do espaço do usuário para o espaço do kernal, enquanto que as chamadas do fprintf vão para a api para o kernal

vivek singh
fonte