As funções-polegar

Caloni, 2009-01-30 computer blog

Como já havia dito, não há nada mais prazeroso do que ensinar a alguém os velhos truques da profissão e relembrar o porquê de tantas coisas que guardamos na cabeça sobre programação. Hoje tive a oportunidade de explicar como funcionam as funções-polegar.

A função-polegar, uma categoria de função muito peculiar em várias APIs, possui um comportamento padrão de retorno de erros. Entre as diversas funções-polegar que conheço e uso, eis algumas que lembro de cor:

  • read, write (C)
  • connect, send (Sockets)
  • ReadFile, WriteFile, CreateProcess (Win32)

O que todas essas funções têm em comum? Bom, ignorando seu funcionamento interno ou seu objetivo, todas elas possuem um valor de retorno no estilo sim ou não, ou seja, deu certo ou não deu. Nessas funções o código de erro, o motivo da função não ter dado certo, não é retornado diretamente. É o que chamo de esquema do polegar pra cima ou polegar pra baixo. O retorno da função especifica o ângulo giratório do dedão:

  • ssize_t pread, ssize_t write. Retorno de -1 significa que deu algo errado.
  • int connect, int send. Se retornar SOCKET_ERROR
  • BOOL ReadFile, BOOL WriteFile, BOOL CreateProcess. TRUE sucesso, FALSE erro.

Por exemplo, chamamos a função ReadFile para ler um arquivo. Ela retorna FALSE. Isso significa que não deu certo nossa leitura. Por quê? Ora, não sabemos ainda. Apenas sabemos que o polegar está virado para baixo!

Em funções nessas condições, geralmente existe uma segunda função (ou variável) que retorna o último erro que ocorreu na API, ou seja, o erro que fez com que última função chamada retornasse que algo não deu certo. Nas funções de exemplo, são usados três métodos distintos, pois estamos falando de três APIs distintas:

  • Variável errno
  • Função WSAGetLastError
  • Função GetLastError

São esses métodos que realmente retornam o porquê da função ter dado errado. E é elas que devemos chamar, eu disse devemos chamar, sempre que a função der errado. Até porque, já que o polegar está virado para baixo, temos que fazer alguma coisa para que nosso programa não morra.

Como bem observado pelo Fernando, nem todas as funções-polegar possuem uma função para obter a causa do erro. Vide SysAllocString, ou mesmo malloc. Nesse caso, não há muito o que determinar a não ser que não foi possível alocar o recurso pedido pelo sistema. Paciência.

// Comments

2009-02-27 Alberto Fabiano:

Olá Caloni,

Usei hoje esta nomenclatura ao comentar com um padawan e ainda indiquei este post! Realmente este alias ficou muito bom.

[]s

A.F.


2009-01-31 Fernando Roberto:

Muito bem explicado Lesma.

Uma coisa importante a se notar na documentação da função a ser usada, é se esta oferece uma função-polegar. Nem todas oferecem esse recurso. É o exemplo da SysAllocString.

Somente a função-polegar indicada na documentação poderá silanizar a causa da falha de uma rotina.

Pode parecer besteira, mas já vi experientes programadores, que na falta de uma função-polegar, chamam a função SetLastError() com ERROR_SUCCESS antes de chamar uma determinada rotina de sistema, e em seguida chamam a GetLastError() para tentar descobrir se algo deu errado durante a chamada.

Isso não faz o menor sentido. Quando você chama uma rotina de terceiro, esta pode utilizar inúmeras chamadas de outras funções, que por sua vez, possuem funções-polegares. Mas neste caso, os valores retornados por elas só serão válidos para a rotina de terceiro que você chamou. Se a rotina de terceiro não indicar uma função-polegar, não tente usar de magia negra para descobrir a causa.

O uso incorreto da função-"polegar" pode sinalizar um "médio" pra cima.

Abraço,

Fernando.


2009-01-31 Caloni:

Olá, Ferdinando.

Pelo visto eu expliquei foi muito mal =)

A função-polegar apenas indica se ela deu certo ou não. O que você chama de função-polegar na verdade é a função-causa, que retorna aí sim o código de erro do que aconteceu (no caso de falhas).

Contudo, bem observado que nem toda função guarda o último erro para o chamador obter posteriormente. Às vezes a função é polegar, como a SysAllocString, mas não possui uma função de causa. Por outro lado, também existem funções não-polegar que são usadas como tal. Já vi programadores tão acostumados com a idéia da função-polegar que usavam o mesmo estilo para as funções do registro (e.g. RegOpenKey) que, como sabemos, já retorna o código de erro diretamente (nesse caso o dedo médio já vem devidamente deslocado).

[]s

[windbg_info] [basico_do_basico_assembly]