stringtranslate.com

Puntero nulo

En informática , un puntero nulo o una referencia nula es un valor guardado para indicar que el puntero o la referencia no se refiere a un objeto válido . Los programas utilizan habitualmente punteros nulos para representar condiciones como el final de una lista de longitud desconocida o la imposibilidad de realizar alguna acción; Este uso de punteros nulos se puede comparar con tipos que aceptan valores NULL y con el valor Nothing en un tipo de opción .

Un puntero nulo no debe confundirse con un puntero no inicializado : se garantiza que un puntero nulo no será igual a cualquier puntero que apunte a un objeto válido. Sin embargo, en general, la mayoría de los idiomas no ofrecen dicha garantía para punteros no inicializados. Podría compararse con otros indicadores válidos; o podría compararse con punteros nulos. Podría hacer ambas cosas en diferentes momentos; o la comparación podría ser un comportamiento indefinido . Además, en los lenguajes que ofrecen dicho soporte, el uso correcto depende de la experiencia individual de cada desarrollador y de las herramientas linter. Incluso cuando se usan correctamente, los punteros nulos son semánticamente incompletos , ya que no ofrecen la posibilidad de expresar la diferencia entre un valor "No aplicable" versus un valor "No conocido" o versus un valor "Futuro".

Debido a que un puntero nulo no apunta a un objeto significativo, un intento de acceder a los datos almacenados en esa ubicación de memoria (no válida) puede causar un error de tiempo de ejecución o una falla inmediata del programa. Este es el error de puntero nulo . Es uno de los tipos más comunes de debilidades del software, [1] y Tony Hoare , quien introdujo el concepto, se ha referido a él como un "error de mil millones de dólares".

C

En C , se garantiza que dos punteros nulos de cualquier tipo serán iguales. [2] La macro del preprocesador NULLse define como una constante de puntero nulo definida por la implementación en , [3] que en C99 se puede expresar de forma portátil como , el valor entero convertido al tipo (consulte puntero al tipo nulo ). [4] El estándar C no dice que el puntero nulo sea el mismo que el puntero a la dirección de memoria  0, aunque ese puede ser el caso en la práctica. Desreferenciar un puntero nulo es un comportamiento indefinido en C, [5] y una implementación conforme puede asumir que cualquier puntero al que se le desreferencia no es nulo.<stdlib.h>((void *)0)0 void*

En la práctica, desreferenciar un puntero nulo puede resultar en un intento de lectura o escritura desde una memoria que no está asignada, lo que desencadena una falla de segmentación o una violación de acceso a la memoria. Esto puede manifestarse como una falla del programa o transformarse en una excepción de software que puede ser detectada por el código del programa. Sin embargo, hay determinadas circunstancias en las que este no es el caso. Por ejemplo, en el modo real x86 , la dirección se puede leer y, por lo general, también se puede escribir, y eliminar la referencia a un puntero a esa dirección es una acción perfectamente válida, pero generalmente no deseada, que puede generar un comportamiento indefinido pero que no bloquea la aplicación. Hay ocasiones en las que desreferenciar el puntero a la dirección cero es intencional y está bien definido; por ejemplo, el código BIOS escrito en C para dispositivos x86 en modo real de 16 bits puede escribir la tabla de descriptores de interrupción (IDT) en la dirección física 0 de la máquina eliminando la referencia a un puntero nulo para escritura. También es posible que el compilador optimice la desreferencia del puntero nulo, evitando un error de segmentación pero provocando otros comportamientos no deseados. [6]0000:0000

C++

En C++, si bien la NULLmacro se heredó de C, tradicionalmente se ha preferido el literal entero para cero para representar una constante de puntero nulo. [7] Sin embargo, C++ 11 introdujo la constante nullptry el tipo de puntero nulo explícito nullptr_tque se utilizará en su lugar.

Otros idiomas

En algunos entornos de lenguaje de programación (al menos una implementación patentada de Lisp, por ejemplo), [ cita necesaria ] el valor utilizado como puntero nulo (llamado nilen Lisp ) puede en realidad ser un puntero a un bloque de datos internos útiles para la implementación (pero no accesible explícitamente desde los programas de usuario), permitiendo así utilizar el mismo registro como una constante útil y una forma rápida de acceder a los componentes internos de la implementación. Esto se conoce como nilvector.

En lenguajes con una arquitectura etiquetada , un puntero posiblemente nulo se puede reemplazar con una unión etiquetada que impone el manejo explícito del caso excepcional; de hecho, un puntero posiblemente nulo puede verse como un puntero etiquetado con una etiqueta calculada.

Los lenguajes de programación utilizan diferentes literales para el puntero nulo . En Python, por ejemplo, un valor nulo se llama None. En Pascal y Swift , se llama a un puntero nulo nil. En Eiffel , se llama voidreferencia.

Desreferenciación nula

Debido a que un puntero nulo no apunta a un objeto significativo, un intento de desreferenciar (es decir, acceder a los datos almacenados en esa ubicación de memoria) un puntero nulo generalmente (pero no siempre) causa un error de tiempo de ejecución o una falla inmediata del programa. MITRE enumera el error del puntero nulo como una de las debilidades del software más comúnmente explotadas. [8]

Mitigación

Existen técnicas para facilitar la depuración de desreferencias de punteros nulos. [11] Bond y otros. [11] sugieren modificar la máquina virtual Java (JVM) para realizar un seguimiento de la propagación nula.

Los lenguajes funcionales puros y el código de usuario ejecutados en muchos lenguajes interpretados o de máquinas virtuales no sufren el problema de la desreferenciación del puntero nulo, ya que no se proporciona acceso directo a los punteros y, en el caso de los lenguajes funcionales puros, todo el código y los datos son inmutables.

Cuando un lenguaje proporciona o utiliza punteros que de otro modo podrían quedar nulos, es posible mitigar o evitar las desreferencias nulas en tiempo de ejecución proporcionando verificación en tiempo de compilación a través de análisis estático u otras técnicas, con un creciente movimiento hacia la asistencia sintáctica de características del lenguaje como los que se ven en las versiones modernas del lenguaje de programación Eiffel , [12] D , [13] y Rust . [14]

Se pueden realizar análisis similares utilizando herramientas externas, en algunos idiomas.

Alternativas a los punteros nulos

Como regla general, para cada tipo de estructura o clase, defina algunos objetos que representen algún estado de la lógica empresarial reemplazando el comportamiento indefinido en nulo. Por ejemplo, "futuro" para indicar un campo dentro de una estructura que no estará disponible en este momento (pero que sabemos de antemano que en un futuro se definirá), "no aplicable" para indicar un campo en una estructura no normalizada estructura, "error", "tiempo de espera" para indicar que el campo no se pudo inicializar (probablemente deteniendo la ejecución normal del programa, subproceso, solicitud o comando completo).

Historia

En 2009, Tony Hoare declaró [15] [16] que inventó la referencia nula en 1965 como parte del lenguaje ALGOL W. En esa referencia de 2009, Hoare describe su invento como un "error de miles de millones de dólares":

Yo lo llamo mi error de mil millones de dólares. Fue la invención de la referencia nula en 1965. En ese momento, estaba diseñando el primer sistema de tipos completo para referencias en un lenguaje orientado a objetos (ALGOL W). Mi objetivo era garantizar que todo uso de referencias fuera absolutamente seguro, y que el compilador realizara la verificación automáticamente. Pero no pude resistir la tentación de incluir una referencia nula, simplemente porque era muy fácil de implementar. Esto ha dado lugar a innumerables errores, vulnerabilidades y caídas del sistema, que probablemente han causado mil millones de dólares en dolores y daños en los últimos cuarenta años.

Ver también

Notas

  1. ^ "CWE-476: Desreferencia de puntero NULO". INGLETA .
  2. ^ ISO/IEC 9899, ​​cláusula 6.3.2.3, párrafo 4.
  3. ^ ISO/IEC 9899, ​​cláusula 7.17, párrafo 3: NULL... que se expande a una constante de puntero nulo definida por la implementación...
  4. ^ ISO/IEC 9899, ​​cláusula 6.3.2.3, párrafo 3.
  5. ^ ab ISO/IEC 9899, ​​cláusula 6.5.3.2, párrafo 4, esp. nota al pie 87.
  6. ^ Lattner, Chris (13 de mayo de 2011). "Lo que todo programador de C debe saber sobre el comportamiento indefinido n.º 1/3". blog.llvm.org . Archivado desde el original el 14 de junio de 2023 . Consultado el 14 de junio de 2023 .
  7. ^ Stroustrup, Bjarne (marzo de 2001). "Capítulo 5: El calificador (§5.4) evita la redefinición accidental y garantiza que se pueda utilizar cuando se requiera una constante". El lenguaje de programación C++ (14ª impresión de la 3ª ed.). Estados Unidos y Canadá: Addison-Wesley. pag. 88.ISBN
    constNULLNULL 0-201-88954-4.
  8. ^ "CWE-476: Desreferencia de puntero NULO". INGLETA .
  9. ^ El lenguaje de programación Objective-C 2.0 , sección "Envío de mensajes a cero".
  10. ^ "Desreferencia del puntero NULL del kernel explotable de OS X en AppleGraphicsDeviceControl"
  11. ^ ab Bond, Michael D.; Nethercote, Nicolás; Kent, Stephen W.; Guyer, Samuel Z.; McKinley, Kathryn S. (2007). "Seguimiento de las manzanas podridas". Actas de la 22ª conferencia anual ACM SIGPLAN sobre sistemas y aplicaciones de programación orientada a objetos - OOPSLA '07 . pag. 405. doi :10.1145/1297027.1297057. ISBN 9781595937865. S2CID  2832749.
  12. ^ "Seguridad del vacío: antecedentes, definición y herramientas" . Consultado el 24 de noviembre de 2021 .
  13. ^ Bartosz Milewski. "Lenguaje de programación SafeD - D" . Consultado el 17 de julio de 2014 .
  14. ^ "Seguridad intrépida: seguridad de la memoria". Archivado desde el original el 8 de noviembre de 2020 . Consultado el 4 de noviembre de 2020 .
  15. ^ Tony Hoare (25 de agosto de 2009). "Referencias nulas: el error de mil millones de dólares". InfoQ.com.
  16. ^ Tony Hoare (25 de agosto de 2009). "Presentación:" Referencias nulas: el error de mil millones de dólares"". InfoQ.com.

Referencias