Ir para conteúdo

Qual dos dois está certo? Os dois!


fredericopissarra

Posts Recomendados

Se você der uma olhada nas manpages de funções como open() e socket(), verá que elas retornam o file descriptor, um inteiro, sinalizado, que corresponde ao "arquivo" aberto. Mas, ambas páginas te dizem que o valor de retorno -1 é um código de erro. No entanto, já vi código assim:

int fd;

if ( ( fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) < 0 )
{ ... trata erro aqui ... }

Estritamente falando, essa comparação com 0 é errada. O valor correspondente a erro é -1 e, em teoria, qualquer outro valor negativo poderia ser usado como um descritor válido. Mas, dando uma olhada na descrição da função, lemos:

Citar

socket()  creates an endpoint for communication and returns a file descriptor that refers to that endpoint.  The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process.

Negrito meu. Só nos resta entender qual seria esse "menor valor numérico". Isso pode ser obtido na descrição da função open():

Citar

The return value of open() is a file descriptor, a small, nonnegative integer that is used in subsequent  system calls.

Negrito também meu... Então, um file descriptor, quando válido, é sempre positivo.

Isso implica que a comparação contra zero é perfeitamente válida e torna nosso código menor. Eis um exemplo do dump de duas funções simples:

; int f( int x ) { return x == -1; }
f:
   0: 31 c0        xor    eax,eax
   2: 83 ff ff     cmp    edi,0xffffffff
   5: 0f 94 c0     sete   al
   8: c3           ret    

; int g( int x ) { return x < 0; }
g:
   0: 89 f8        mov    eax,edi
   2: c1 e8 1f     shr    eax,31
   5: c3           ret

Tudo o que a função g() precisa fazer é verificar o sinal de x, daí o deslocamento de 31 bits para a esquerda do valor de EAX. A função f(), embora não seja assim tão ruim, realiza uma operação aritmética (CMP) e altera EAX em dois pontos, já g() apenas faz a alterção de EAX... Sem contar que g() gasta 4 bytes a menos nas instruções, colocando menos pressão no cache L1i.

Existe um limite superior, default, para a quantidade de descritores que podem ser abertos por processo:

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 31542
max locked memory       (kbytes, -l) 16384
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 31542
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Veja a linha "open files". No máximo, por default, um processo pode abrir até 1024 descritores. Destes, temos que descontar os 3 descritores default (stdin, stdout e stderr; 0, 1 e 2, respectivamente), restando 1021 descritores disponíveis para um processo. Assim, um file descritor não ocupará mais que 10 bits de tamanho se esse limite não for alterado e, mesmo que seja, um int tem 31 bits de precisão, possibilitando o valor máximo de um descritor de 2³¹-1 ou 2147483647 arquivos abertos por processo (isso é um exagero e se for permitido e essa quantidade alcançada, consumirá muita memória e tornará seu sistema lentíssimo!).

Então, comparar a condição de erro contra 0 e não contra -1, é perfeitamente seguro. A não ser que você queira que seu código seja totalmente portável...

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...