He estado aprendiendo C ++ y me está costando entender nulo. En particular, los tutoriales que he leído mencionan hacer una "verificación nula", pero no estoy seguro de lo que eso significa o por qué es necesario.
- ¿Qué es exactamente nulo?
- ¿Qué significa "verificar nulo"?
- ¿Siempre necesito verificar si es nulo?
Cualquier código de ejemplo sería muy apreciado.
Respuestas:
En C y C ++, los punteros son intrínsecamente inseguros, es decir, cuando desreferencia un puntero, es su responsabilidad asegurarse de que apunte a algún lugar válido; esto es parte de lo que se trata la "administración de memoria manual" (a diferencia de los esquemas automáticos de administración de memoria implementados en lenguajes como Java, PHP o .NET runtime, que no le permitirán crear referencias inválidas sin un esfuerzo considerable).
Una solución común que detecta muchos errores es establecer todos los punteros que no apuntan a nada como
NULL
(o, en C ++ correcto0
), y verificar eso antes de acceder al puntero. Específicamente, es una práctica común inicializar todos los punteros a NULL (a menos que ya tenga algo para señalarlos cuando los declara), y establecerlos en NULL cuando usteddelete
ofree()
ellos (a menos que salgan del alcance inmediatamente después de eso). Ejemplo (en C, pero también en C ++ válido):Una mejor versión:
Sin la verificación nula, pasar un puntero NULL a esta función causará una falla por defecto, y no hay nada que pueda hacer: el sistema operativo simplemente matará su proceso y tal vez volcará el núcleo o abrirá un cuadro de diálogo de informe de bloqueo. Con la verificación nula en su lugar, puede realizar un manejo de errores adecuado y recuperarse con gracia: corrija el problema usted mismo, cancele la operación actual, escriba una entrada de registro, notifique al usuario, lo que sea apropiado.
fuente
Las otras respuestas cubrieron su pregunta exacta. Se realiza una comprobación nula para asegurarse de que el puntero que recibió en realidad apunta a una instancia válida de un tipo (objetos, primitivas, etc.).
Sin embargo, voy a agregar mi propio consejo aquí. Evitar cheques nulos. :) Las comprobaciones nulas (y otras formas de programación defensiva) desordenan el código, y en realidad lo hacen más propenso a errores que otras técnicas de manejo de errores.
Mi técnica favorita cuando se trata de punteros de objetos es usar el patrón Objeto nulo . Eso significa devolver una (puntero, o incluso mejor, una referencia a una) matriz o lista vacía en lugar de nula, o devolver una cadena vacía ("") en lugar de nula, o incluso la cadena "0" (o algo equivalente a "nada "en el contexto) donde espera que se analice a un entero.
Como beneficio adicional, aquí hay algo que quizás no sabías sobre el puntero nulo, que fue implementado (por primera vez) por CAR Hoare para el lenguaje Algol W en 1965.
fuente
El valor del puntero nulo representa un "ningún lugar" bien definido; es un valor de puntero inválido que se garantiza que no se compara con ningún otro valor de puntero. Intentar desreferenciar un puntero nulo da como resultado un comportamiento indefinido y generalmente generará un error de tiempo de ejecución, por lo que debe asegurarse de que un puntero no sea NULL antes de intentar desreferenciarlo. Varias funciones de la biblioteca C y C ++ devolverán un puntero nulo para indicar una condición de error. Por ejemplo, la función de biblioteca
malloc
devolverá un valor de puntero nulo si no puede asignar el número de bytes que se han solicitado, e intentar acceder a la memoria a través de ese puntero (generalmente) provocará un error de tiempo de ejecución:Por lo tanto, debemos asegurarnos de que la
malloc
llamada se realizó correctamente comprobando el valor dep
contra NULL:Ahora, agárrate a tus calcetines un minuto, esto se pondrá un poco irregular.
Hay un puntero nulo valor y un puntero nulo constante , y los dos no son necesariamente los mismos. El puntero nulo valor es cualquier valor que los usos arquitectura subyacente para representar "la nada". Este valor puede ser 0x00000000, 0xFFFFFFFF, 0xDEADBEEF o algo completamente diferente. No asuma que el puntero nulo valor es siempre 0.
La constante de puntero nulo , OTOH, es siempre una expresión integral con valor 0. En lo que respecta a su código fuente , 0 (o cualquier expresión integral que evalúe a 0) representa un puntero nulo. Tanto C como C ++ definen la macro NULL como la constante de puntero nulo. Cuando se compila su código, la constante de puntero nulo se reemplazará con el valor de puntero nulo apropiado en el código de máquina generado.
Además, tenga en cuenta que NULL es solo uno de los muchos valores de puntero inválidos posibles ; si declara una variable de puntero automático sin inicializarla explícitamente, como
El valor inicialmente almacenado en la variable es indeterminado y puede no corresponder a una dirección de memoria válida o accesible. Desafortunadamente, no hay forma (portátil) de saber si un valor de puntero no NULL es válido o no antes de intentar usarlo. Entonces, si está tratando con punteros, generalmente es una buena idea inicializarlos explícitamente a NULL cuando los declara, y establecerlos en NULL cuando no apuntan activamente a nada.
Tenga en cuenta que esto es más un problema en C que en C ++; C ++ idiomático no debería usar punteros tanto.
fuente
Hay un par de métodos, todos esencialmente hacen lo mismo.
comprobación nula (comprobar si el puntero es nulo), versión A
cheque nulo, versión B
cheque nulo, versión C
De los tres, prefiero usar la primera verificación, ya que explícitamente le dice a los futuros desarrolladores lo que estaba tratando de verificar Y deja en claro que esperaba que foo fuera un puntero.
fuente
Usted no La única razón para usar un puntero en C ++ es porque desea explícitamente la presencia de punteros nulos; de lo contrario, puede tomar una referencia, que es semánticamente más fácil de usar y garantiza que no sea nulo.
fuente
export
) y todas las características de la biblioteca C ++ 03 y TR1 y una buena parte de C ++ 11.Si no marca el valor NULL, especialmente, si eso es un puntero a una estructura, tal vez haya encontrado una vulnerabilidad de seguridad: la desreferencia de puntero NULL. La desreferencia de puntero NULO puede conducir a otras vulnerabilidades de seguridad graves, como desbordamiento del búfer, condición de carrera ... que pueden permitir que el atacante tome el control de su computadora.
Muchos proveedores de software como Microsoft, Oracle, Adobe, Apple ... lanzan parches de software para corregir estas vulnerabilidades de seguridad. Creo que deberías comprobar el valor NULL de cada puntero :)
fuente