Eu tenho aprendido C ++ e estou tendo dificuldade em entender nulo. Em particular, os tutoriais que li mencionam fazer uma "verificação nula", mas não tenho certeza do que isso significa ou por que é necessário.
- O que exatamente é nulo?
- O que significa "procurar nulo"?
- Sempre preciso verificar se há nulo?
Qualquer exemplo de código seria muito apreciado.
Respostas:
Em C e C ++, os ponteiros são inerentemente inseguros, ou seja, quando você desreferencia um ponteiro, é de sua responsabilidade garantir que ele aponte para algum lugar válido; isso faz parte do objetivo do "gerenciamento manual de memória" (em oposição aos esquemas de gerenciamento automático de memória implementados em linguagens como Java, PHP ou runtime do .NET, que não permitem criar referências inválidas sem grande esforço).
Uma solução comum que captura muitos erros é definir todos os ponteiros que não apontam para nada como
NULL
(ou, no C ++ correto0
) e verificar isso antes de acessar o ponteiro. Especificamente, é prática comum inicializar todos os ponteiros para NULL (a menos que você já tenha algo para apontá-los quando os declarar) e configurá-los para NULL quando vocêdelete
oufree()
eles (a menos que eles fiquem fora do escopo imediatamente depois disso). Exemplo (em C, mas também em C ++ válido):Uma versão melhor:
Sem a verificação nula, passar um ponteiro NULL para essa função causará um segfault, e não há nada que você possa fazer - o sistema operacional simplesmente interrompe seu processo e talvez despeje o núcleo ou apareça uma caixa de diálogo de relatório de falha. Com a verificação nula, você pode executar o tratamento adequado dos erros e se recuperar normalmente - corrija o problema sozinho, interrompa a operação atual, escreva uma entrada de log, notifique o usuário, o que for apropriado.
fonte
As outras respostas cobriram praticamente sua pergunta exata. Uma verificação nula é feita para garantir que o ponteiro que você recebeu realmente aponte para uma instância válida de um tipo (objetos, primitivas, etc.).
Vou adicionar meu próprio conselho aqui, no entanto. Evite verificações nulas. :) Verificações nulas (e outras formas de programação defensiva) desorganizam o código e, na verdade, o tornam mais propenso a erros do que outras técnicas de tratamento de erros.
Minha técnica favorita quando se trata de ponteiros de objeto é usar o padrão Null Object . Isso significa retornar uma (ponteiro - ou melhor ainda, referência a) matriz ou lista vazia em vez de nula, ou retornar uma string vazia ("") em vez de null, ou mesmo a string "0" (ou algo equivalente a "nothing "no contexto) em que você espera que seja analisado para um número inteiro.
Como bônus, aqui está uma coisinha que você talvez não soubesse sobre o ponteiro nulo, que foi (formalmente formalmente) implementado pelo CAR Hoare para a linguagem Algol W em 1965.
fonte
O valor do ponteiro nulo representa um "lugar nenhum" bem definido; é um valor de ponteiro inválido que é garantido para comparar com qualquer outro valor de ponteiro. Tentar desreferenciar um ponteiro nulo resulta em um comportamento indefinido e geralmente levará a um erro de tempo de execução. Portanto, você deseja garantir que um ponteiro não seja NULL antes de tentar desreferê-lo. Um número de funções da biblioteca C e C ++ retornará um ponteiro nulo para indicar uma condição de erro. Por exemplo, a função de biblioteca
malloc
retornará um valor de ponteiro nulo se não puder alocar o número de bytes que foram solicitados, e tentar acessar a memória através desse ponteiro (normalmente) levará a um erro de tempo de execução:Portanto, precisamos garantir que a
malloc
chamada tenha êxito, verificando o valor dep
contra NULL:Agora, segure suas meias por um minuto, isso vai ficar um pouco acidentado.
Há um valor de ponteiro nulo e uma constante de ponteiro nulo , e os dois não são necessariamente os mesmos. O valor do ponteiro nulo é o valor que a arquitetura subjacente usa para representar "lugar nenhum". Este valor pode ser 0x00000000 ou 0xFFFFFFFF ou 0xDEADBEEF ou algo completamente diferente. Não suponha que o valor do ponteiro nulo seja sempre 0.
A constante de ponteiro nulo , OTOH, é sempre uma expressão integral com valor 0. No que diz respeito ao seu código-fonte , 0 (ou qualquer expressão integral avaliada como 0) representa um ponteiro nulo. C e C ++ definem a macro NULL como a constante de ponteiro nulo. Quando seu código é compilado, a constante de ponteiro nulo será substituída pelo valor apropriado de ponteiro nulo no código de máquina gerado.
Além disso, esteja ciente de que NULL é apenas um dos muitos possíveis valores inválidos de ponteiro; se você declarar uma variável de ponteiro automático sem inicializá-la explicitamente, como
o valor inicialmente armazenado na variável é indeterminado e pode não corresponder a um endereço de memória válido ou acessível. Infelizmente, não há uma maneira (portátil) de saber se um valor de ponteiro não NULL é válido ou não antes de tentar usá-lo. Portanto, se você estiver lidando com ponteiros, geralmente é uma boa ideia inicializá-los explicitamente para NULL quando você os declarar e defini-los como NULL quando não estiverem apontando ativamente para nada.
Observe que isso é mais um problema em C do que em C ++; o C ++ idiomático não deve usar tanto os ponteiros.
fonte
Existem alguns métodos, todos essencialmente fazem a mesma coisa.
verificação nula (verifique se o ponteiro é nulo), versão A
verificação nula, versão B
verificação nula, versão C
Dos três, prefiro usar a primeira verificação, pois ela explicitamente informa aos futuros desenvolvedores o que você estava tentando verificar E deixa claro que você esperava que foo fosse um ponteiro.
fonte
Você não O único motivo para usar um ponteiro em C ++ é porque você deseja explicitamente a presença de ponteiros nulos; caso contrário, você pode obter uma referência, que é semanticamente mais fácil de usar e garante que não é nulo.
fonte
export
) e todos os recursos da biblioteca C ++ 03 e TR1 e uma boa parte do C ++ 11.Se você não verificar o valor NULL, especialmente se esse é um ponteiro para uma estrutura, talvez você encontre uma vulnerabilidade de segurança - desreferência de ponteiro NULL. A dereferência de ponteiro NULL pode levar a outras vulnerabilidades graves de segurança, como estouro de buffer, condição de corrida ... que podem permitir que o invasor assuma o controle do seu computador.
Muitos fornecedores de software como Microsoft, Oracle, Adobe, Apple ... lançam patches de software para corrigir essas vulnerabilidades de segurança. Eu acho que você deve verificar o valor NULL de cada ponteiro :)
fonte