Articulo de referencia

Número mágico (programación)

En programación informática , un número mágico es cualquiera de los siguientes: Un valor único con un significado inexplicable o múltiples ocurrencias que podrían (preferiblemen...

En programación informática , un número mágico es cualquiera de los siguientes:

  • Un valor único con un significado inexplicable o múltiples ocurrencias que podrían (preferiblemente) reemplazarse con una constante nombrada
  • Un valor numérico o de texto constante que se utiliza para identificar un formato de archivo o un protocolo (para archivos, consulte Lista de firmas de archivos )
  • Un valor único distintivo que es poco probable que se confunda con otros significados (por ejemplo, identificadores únicos globales )

Constantes numéricas sin nombre

El término número mágico o constante mágica se refiere al antipatrón de usar números directamente en el código fuente. Esto se ha considerado como una violación de una de las reglas más antiguas de la programación, que se remonta a los manuales COBOL , FORTRAN y PL/1 de la década de 1960. [1] El uso de números mágicos sin nombre en el código oscurece la intención de los desarrolladores al elegir ese número, [2] aumenta las oportunidades de errores sutiles (por ejemplo, ¿es correcto cada dígito en 3.14159265358979323846 y se puede redondear a 3.14159? [3] ) y hace que sea más difícil que el programa se adapte y amplíe en el futuro. [4] Reemplazar todos los números mágicos significativos con constantes con nombre (también llamadas variables explicativas) hace que los programas sean más fáciles de leer, comprender y mantener. [5]

Los nombres elegidos para que tengan significado en el contexto del programa pueden dar como resultado un código que sea más fácil de entender para un mantenedor que no sea el autor original (o incluso para el autor original después de un período de tiempo). [6] Un ejemplo de una constante con un nombre poco informativo es int SIXTEEN = 16, mientras que int NUMBER_OF_BITS = 16es más descriptivo.

Los problemas asociados con los 'números' mágicos descritos anteriormente no se limitan a los tipos numéricos y el término también se aplica a otros tipos de datos donde declarar una constante nombrada sería más flexible y comunicativo. [1] Por lo tanto, declarar const string testUserName = "John"es mejor que varias apariciones del 'valor mágico' "John"en un conjunto de pruebas .

Por ejemplo, si se requiere mezclar aleatoriamente los valores de una matriz que representa una baraja de cartas estándar , este pseudocódigo hace el trabajo utilizando el algoritmo de mezcla de Fisher-Yates :

para i del 1 al 52
    j := i + int aleatorio (53 - i) - 1
    a.swapEntries(i, j)

donde aes un objeto de matriz, la función randomInt(x)elige un entero aleatorio entre 1 y x , ambos inclusive, e swapEntries(i, j)intercambia las entradas i y j de la matriz. En el ejemplo anterior, 52es un número mágico. Se considera que un mejor estilo de programación es escribir lo siguiente:

int deckSize:= 52
 para i desde 1 hasta deckSize
    j := i + randomInt(tamañoBaraja + 1 - i) - 1
    a.swapEntries(i, j)

Esto es preferible por varias razones:

  • Es más fácil de leer y comprender. Un programador que lea el primer ejemplo podría preguntarse: ¿Qué significa el número 52 aquí? ¿Por qué 52? El programador podría inferir el significado después de leer el código con atención, pero no es obvio. [6] Los números mágicos se vuelven particularmente confusos cuando el mismo número se usa para diferentes propósitos en una sección del código.
  • Es más fácil alterar el valor del número, ya que no está duplicado. Cambiar el valor de un número mágico es propenso a errores, porque el mismo valor a menudo se usa varias veces en diferentes lugares dentro de un programa. [6] Además, cuando dos variables o números semánticamente distintos tienen el mismo valor, pueden ser editados accidentalmente juntos. [6] Para modificar el primer ejemplo para barajar una baraja de Tarot , que tiene 78 cartas, un programador podría reemplazar ingenuamente cada instancia de 52 en el programa con 78. Esto causaría dos problemas. Primero, perdería el valor 53 en la segunda línea del ejemplo, lo que haría que el algoritmo fallara de manera sutil. Segundo, probablemente reemplazaría los caracteres "52" en todas partes, independientemente de si se refieren al tamaño de la baraja o a algo completamente diferente, como el número de semanas en un año del calendario gregoriano, o más insidiosamente, son parte de un número como "1523", todo lo cual introduciría errores. Por el contrario, cambiar el valor de la deckSizevariable en el segundo ejemplo sería un cambio simple de una línea.
  • Fomenta y facilita la documentación. [6] El lugar único donde se declara la variable nombrada es un buen lugar para documentar lo que significa el valor y por qué tiene el valor que tiene. Tener el mismo valor en una gran cantidad de lugares conduce a comentarios duplicados (y problemas asociados cuando se actualizan algunos pero se omiten otros) o no deja un lugar donde sea natural para el autor explicar el valor y probablemente el lector busque una explicación.
  • Las declaraciones de variables de "número mágico" se colocan juntas, generalmente en la parte superior de una función o archivo, lo que facilita su revisión y modificación. [6]
  • Ayuda a detectar errores tipográficos . El uso de una variable (en lugar de un literal) aprovecha la comprobación del compilador. Escribir accidentalmente "62" en lugar de "52" no se detectaría, mientras que escribir " dekSize" en lugar de " deckSize" daría como resultado la advertencia del compilador de que dekSizeno se ha declarado.
  • Puede reducir la cantidad de escritura en algunos IDE . Si un IDE admite la función de completado de código , completará la mayor parte del nombre de la variable a partir de las primeras letras.
  • Facilita la parametrización. Por ejemplo, para generalizar el ejemplo anterior a un procedimiento que baraje una baraja de cualquier número de cartas, bastaría con convertir deckSizeen un parámetro de dicho procedimiento, mientras que el primer ejemplo requeriría varios cambios.
función shuffle ( int deckSize)
    para i desde 1 hasta deckSize
       j := i + randomInt(tamañoBaraja + 1 - i) - 1
       a.swapEntries(i, j)

Las desventajas son:

  • Cuando la constante nombrada no se define cerca de su uso, se perjudica la localidad y, por lo tanto, la comprensión del código. Poner el 52 en un lugar posiblemente distante significa que, para entender completamente el funcionamiento del bucle "for" (por ejemplo, para estimar el tiempo de ejecución del bucle), uno debe rastrear la definición y verificar que sea el número esperado. Esto es fácil de evitar (reubicando la declaración) cuando la constante solo se usa en una parte del código. Por otro lado, cuando la constante nombrada se usa en partes dispares, la ubicación remota es una pista para el lector de que el mismo valor aparece en otros lugares del código, lo que también puede valer la pena investigar.
  • Puede hacer que el código sea más verboso. La declaración de la constante agrega una línea. Cuando el nombre de la constante es más largo que el del valor, particularmente si varias de estas constantes aparecen en una línea, puede ser necesario dividir una declaración lógica del código en varias líneas. Un aumento en la verbosidad puede estar justificado cuando existe alguna probabilidad de confusión sobre la constante, o cuando existe la posibilidad de que la constante deba cambiarse, como la reutilización de una rutina de barajado para otros juegos de cartas. También puede justificarse como un aumento en la expresividad.
  • Puede resultar más lento procesar la expresión deckSize + 1en tiempo de ejecución que el valor "53", aunque la mayoría de los compiladores e intérpretes modernos notarán que deckSizese ha declarado como una constante y calcularán previamente el valor 53 en el código compilado. Incluso cuando eso no sea una opción, la optimización del bucle moverá la adición para que se realice antes del bucle. Por lo tanto, normalmente no hay ninguna penalización de velocidad (o esta es insignificante) en comparación con el uso de números mágicos en el código. Especialmente el costo de la depuración y el tiempo necesario para tratar de comprender el código no explicativo deben compararse con el pequeño costo de cálculo.

Usos aceptados

En algunos contextos, el uso de constantes numéricas sin nombre es generalmente aceptado (y posiblemente "no sea mágico"). Si bien dicha aceptación es subjetiva y a menudo depende de los hábitos de codificación individuales, los siguientes son ejemplos comunes:

  • el uso de 0 y 1 como valores iniciales o incrementales en un bucle for , comofor (int i = 0; i < max; i += 1)
  • el uso de 2 para comprobar si un número es par o impar, como en isEven = (x % 2 == 0), donde %es el operador módulo
  • el uso de constantes aritméticas simples, por ejemplo, en expresiones como circumference = 2 * Math.PI * radius, [1] o para calcular el discriminante de una ecuación cuadrática comod = b^2 − 4*a*c
  • el uso de potencias de 10 para convertir valores métricos (por ejemplo, entre gramos y kilogramos) o para calcular valores porcentuales y por mil
  • exponentes en expresiones como (f(x) ** 2 + f(y) ** 2) ** 0.5para F ( incógnita ) 2 + F ( y ) 2 {\displaystyle {\sqrt {f(x)^{2}+f(y)^{2}}}}

Las constantes 1 y 0 se utilizan a veces para representar los valores booleanos true y false en lenguajes de programación sin un tipo booleano, como las versiones anteriores de C. La mayoría de los lenguajes de programación modernos proporcionan un tipo primitivoboolean o , por lo que el uso de 0 y 1 no es recomendable. Esto puede ser más confuso ya que 0 a veces significa éxito programático (cuando -1 significa fracaso) y fracaso en otros casos (cuando 1 significa éxito). bool

En C y C++, 0 representa el puntero nulo . Al igual que con los valores booleanos, la biblioteca estándar de C incluye una definición de macro NULLcuyo uso se recomienda. Otros lenguajes proporcionan un valor nullor específico nily, cuando este es el caso, no se debe utilizar ninguna alternativa. La constante de puntero tipado nullptrse introdujo con C++11.

Indicadores de formato

Origen

Los indicadores de formato se utilizaron por primera vez en el código fuente de Unix de la versión 7. [ cita requerida ]

Unix fue portado a uno de los primeros DEC PDP-11 /20s, que no tenía protección de memoria . Por lo tanto, las primeras versiones de Unix usaban el modelo de referencia de memoria reubicable . [7] Las versiones de Unix anteriores a la Sexta Edición leían un archivo ejecutable en la memoria y saltaban a la primera dirección de memoria baja del programa, la dirección relativa cero. Con el desarrollo de versiones paginadas de Unix, se creó un encabezado para describir los componentes de la imagen ejecutable . Además, se insertó una instrucción de bifurcación como la primera palabra del encabezado para omitir el encabezado e iniciar el programa. De esta manera, un programa podía ejecutarse en el antiguo modo de referencia de memoria reubicable (regular) o en modo paginado. A medida que se desarrollaron más formatos ejecutables, se agregaron nuevas constantes incrementando el desplazamiento de la bifurcación . [8]

En el código fuente de la sexta edición del cargador de programas de Unix, la función exec() leía la imagen ejecutable ( binaria ) del sistema de archivos. Los primeros 8 bytes del archivo eran un encabezado que contenía los tamaños del programa (texto) y las áreas de datos inicializadas (globales). Además, la primera palabra de 16 bits del encabezado se comparaba con dos constantes para determinar si la imagen ejecutable contenía referencias de memoria reubicables (normal), la imagen ejecutable de solo lectura paginada recientemente implementada o la imagen paginada de instrucciones y datos separados. [9] No se mencionaba el papel dual de la constante del encabezado, pero el byte de orden superior de la constante era, de hecho, el código de operación para la instrucción de bifurcación PDP-11 ( octal 000407 o hexadecimal 0107). Agregar siete al contador del programa mostraba que si se ejecutaba esta constante , ramificaría el servicio exec() de Unix sobre el encabezado de ocho bytes de la imagen ejecutable e iniciaría el programa.

Dado que la sexta y séptima ediciones de Unix empleaban código de paginación, el doble papel de la constante de encabezado estaba oculto. Es decir, el servicio exec() leía los datos de encabezado del archivo ejecutable ( meta ) en un búfer de espacio del núcleo , pero leía la imagen ejecutable en el espacio del usuario , por lo que no utilizaba la característica de ramificación de la constante. La creación de números mágicos se implementó en el enlazador y cargador de Unix y la ramificación de números mágicos probablemente todavía se usaba en el conjunto de programas de diagnóstico independientes que venían con la sexta y séptima ediciones. Por lo tanto, la constante de encabezado proporcionaba una ilusión y cumplía los criterios para ser mágica .

En la versión siete de Unix, la constante de encabezado no se probaba directamente, sino que se asignaba a una variable denominada ux_mag [10] y, posteriormente, se la denominaba número mágico . Probablemente debido a su singularidad, el término número mágico pasó a significar tipo de formato ejecutable, luego se expandió para significar tipo de sistema de archivos y se expandió nuevamente para significar cualquier tipo de archivo.

En archivos

Los números mágicos son comunes en programas de muchos sistemas operativos. Los números mágicos implementan datos fuertemente tipados y son una forma de señalización en banda para el programa de control que lee los tipos de datos en tiempo de ejecución del programa. Muchos archivos tienen constantes de este tipo que identifican los datos que contienen. Detectar dichas constantes en los archivos es una forma simple y efectiva de distinguir entre muchos formatos de archivo y puede brindar más información en tiempo de ejecución .

Ejemplos
Detección

El programa de utilidad de Unix filepuede leer e interpretar números mágicos de archivos, y el archivo que se utiliza para analizar la información se llama magic . La utilidad de Windows TrID tiene una finalidad similar.

En protocolos

Ejemplos
  • El protocolo OSCAR , utilizado en AIM / ICQ , antepone las solicitudes con 2A.
  • En el protocolo RFB utilizado por VNC , un cliente inicia su conversación con un servidor enviando "RFB" ( 52 46 42, por "Remote Frame Buffer") seguido del número de versión del protocolo del cliente.
  • En el protocolo SMB utilizado por Microsoft Windows, cada solicitud SMB o respuesta del servidor comienza con ' FF 53 4D 42', o "\xFFSMB"al inicio de la solicitud SMB.
  • En el protocolo MSRPC que utiliza Microsoft Windows, cada solicitud basada en TCP comienza con 05al inicio de la solicitud (que representa Microsoft DCE/RPC versión 5), seguido inmediatamente por un 00o 01para la versión secundaria. En las solicitudes MSRPC basadas en UDP, el primer byte siempre es 04.
  • En las interfaces serializadas COM y DCOM , llamadas OBJREF , siempre comience con la secuencia de bytes "MEOW" ( 4D 45 4F 57). Las extensiones de depuración (usadas para el enlace de canales DCOM) están precedidas por la secuencia de bytes "MARB" ( 4D 41 52 42).
  • Las solicitudes de seguimiento de BitTorrent sin cifrar comienzan con un solo byte que contiene el valor 19que representa la longitud del encabezado, seguido inmediatamente por la frase "protocolo BitTorrent" en la posición de byte 1.
  • El tráfico de eDonkey2000 / eMule comienza con un solo byte que representa la versión del cliente. Actualmente E3representa un cliente eDonkey, C5representa eMule y D4representa eMule comprimido.
  • Los primeros 4 bytes de un bloque en la cadena de bloques de Bitcoin contienen un número mágico que sirve como identificador de red. El valor es una constante 0xD9B4BEF9que indica la red principal, mientras que la constante 0xDAB5BFFAindica la red de prueba.
  • Las transacciones SSL siempre comienzan con un mensaje de "saludo del cliente". El esquema de encapsulación de registros utilizado para prefijar todos los paquetes SSL consta de formatos de encabezado de dos y tres bytes. Normalmente, un mensaje de saludo del cliente de SSL versión 2 tiene como prefijo un 80y una respuesta del servidor SSLv3 a un saludo del cliente comienza con 16(aunque esto puede variar).
  • Los paquetes DHCP utilizan un valor de "cookie mágica" de " 0x63 0x82 0x53 0x63" al comienzo de la sección de opciones del paquete. Este valor se incluye en todos los tipos de paquetes DHCP.
  • Las conexiones HTTP/2 se abren con el prefacio ' 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a' o " PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n". El prefacio está diseñado para evitar el procesamiento de tramas por parte de servidores e intermediarios que admiten versiones anteriores de HTTP pero no la 2.0.

En interfaces

Los números mágicos son comunes en las funciones e interfaces de API en muchos sistemas operativos , incluidos DOS , Windows y NetWare :

Ejemplos
  • Las BIOS compatibles con IBM PC utilizan valores mágicos 0000para 1234decidir si el sistema debe contar la memoria o no al reiniciar, realizando así un arranque en frío o en caliente. Estos valores también son utilizados por los administradores de memoria EMM386 que interceptan las solicitudes de arranque. [13] Las BIOS también utilizan valores mágicos 55 AApara determinar si un disco es arrancable. [14]
  • La caché de disco MS-DOS SMARTDRV (nombre en código "Bambi") utiliza los valores mágicos BABE y EBAB en las funciones API. [13]
  • Muchos controladores DR DOS , Novell DOS y OpenDOS desarrollados en el antiguo Centro de Desarrollo Europeo en el Reino Unido utilizan el valor 0EDC como token mágico al invocar o proporcionar funcionalidad adicional sobre las funciones DOS estándar (emuladas), siendo NWCACHE un ejemplo. [13]

Otros usos

Ejemplos

Límites de tipos de datos

Esta es una lista de límites de los tipos de almacenamiento de datos: [16]

GUID

Es posible crear o alterar identificadores únicos globales (GUID) para que sean memorables, pero esto se desaconseja enfáticamente ya que compromete su fortaleza como identificadores casi únicos. [17] [18] Las especificaciones para generar GUID y UUID son bastante complejas, lo que lleva a que sean virtualmente únicos, si se implementan correctamente. [19]

Los números de identificación de producto de Microsoft Windows para productos de Microsoft Office a veces terminan con 0000-0000-0000000FF1CE("OFFICE"), como { 90160000-008C-0000-0000-0000000FF1CE}, el identificador de producto para el "Componente de extensibilidad de hacer clic y ejecutar de Office 16".

Java utiliza varios GUID que comienzan con CAFEEFAC. [20]

En la tabla de particiones GUID del esquema de particionamiento GPT, las particiones de arranque del BIOS utilizan el GUID especial { 21686148-6449-6E6F-744E-656564454649} [21] que no sigue la definición de GUID; en su lugar, se forma utilizando los códigos ASCIIHah!IdontNeedEFI para la cadena " " parcialmente en orden little endian . [22]

Valores de depuración

Los valores de depuración mágicos son valores específicos que se escriben en la memoria durante la asignación o desasignación, de modo que más tarde sea posible saber si se han corrompido o no, y para que sea obvio cuando se están utilizando valores tomados de la memoria no inicializada. La memoria suele verse en hexadecimal, por lo que es común recordar valores repetidos o en lenguaje hexadecimal . Se pueden preferir valores numéricamente impares para que los procesadores sin direccionamiento de bytes fallen al intentar usarlos como punteros (que deben caer en direcciones pares). Se deben elegir valores que estén lejos de las direcciones probables (el código del programa, los datos estáticos, los datos del montón o la pila). De manera similar, se pueden elegir de modo que no sean códigos válidos en el conjunto de instrucciones para la arquitectura dada.

Dado que es muy poco probable, aunque posible, que un entero de 32 bits tome este valor específico, la aparición de dicho número en un depurador o en un volcado de memoria probablemente indique un error, como un desbordamiento de búfer o una variable no inicializada .

Algunos ejemplos famosos y comunes incluyen:

La mayoría de estos tienen una longitud de 32 bits : el tamaño de palabra de la mayoría de las computadoras con arquitectura de 32 bits.

La prevalencia de estos valores en la tecnología de Microsoft no es casualidad; se analizan en detalle en el libro de Steve Maguire Writing Solid Code de Microsoft Press . El autor ofrece una variedad de criterios para estos valores, como:

  • No deberían ser útiles, es decir, se debería esperar que la mayoría de los algoritmos que operan con ellos hagan algo inusual. Los números como el cero no cumplen este criterio.
  • El programador debería poder reconocerlos fácilmente como valores no válidos en el depurador.
  • En las máquinas que no tienen alineación de bytes , deben ser números impares , de modo que desreferenciarlos como direcciones provoque una excepción.
  • Deberían provocar una excepción, o quizás incluso una interrupción del depurador, si se ejecutan como código.

Dado que a menudo se utilizaban para marcar áreas de memoria que estaban esencialmente vacías, algunos de estos términos llegaron a utilizarse en frases que significaban "desaparecido, abortado, borrado de la memoria"; por ejemplo, "Su programa está MUERTO". [ cita requerida ]

Véase también

Referencias

  1. ^ abc Martin, Robert C. (2009). "Capítulo 17: Olores y heurísticas - G25 Reemplazar números mágicos por constantes nombradas". Clean Code - A handbook of agile software craftsmanship . Boston: Prentice Hall. pág. 300. ISBN 978-0-13-235088-4.
  2. ^ Martin, Robert C. (2009). "Capítulo 17: Olores y heurísticas - G16 Obscured Intent". Clean Code - A handbook of agile software craftsmanship . Boston: Prentice Hall. pág. 295. ISBN 978-0-13-235088-4.
  3. ^ Contieri, Maxi (2020-10-20). "Code Smell 02 - Constantes y números mágicos". Maximiliano Contieri - Diseño de software . Consultado el 21 de marzo de 2024 .
  4. ^ Maguire, James (9 de diciembre de 2008). "Bjarne Stroustrup sobre la educación de los desarrolladores de software". Datamation.com . Archivado desde el original el 23 de junio de 2018.
  5. ^ Vogel, Jeff (29 de mayo de 2007). "Seis maneras de escribir código más comprensible". IBM Developer . Archivado desde el original el 26 de septiembre de 2018.
  6. ^ abcdef Paul, Matthias R. (9 de abril de 2002). «[fd-dev] CuteMouse 2.0 alpha 1». freedos-dev . Archivado desde el original el 7 de abril de 2022 . Consultado el 4 de agosto de 2022 .
  7. ^ "Comentarios extraños y hechos extraños en Unix". Bell Labs . 22 de junio de 2002. Archivado desde el original el 4 de noviembre de 2006.
  8. ^ Comunicación personal con Dennis M. Ritchie.
  9. ^ "El árbol Unix V6/usr/sys/ken/sys1.c". The Unix Heritage Society . Archivado desde el original el 26 de marzo de 2023.
  10. ^ "El árbol Unix V7/usr/sys/sys/sys1.c". The Unix Heritage Society . Archivado desde el original el 26 de marzo de 2023.
  11. ^ "Especificación PNG (Portable Network Graphics) Versión 1.0: 12.11. Firma del archivo PNG". MIT . 1996-10-01. Archivado desde el original el 2023-03-26.
  12. ^ Chen, Raymond (24 de marzo de 2008). "¿Cuál es la diferencia entre las extensiones COM y EXE?". The Old New Thing . Archivado desde el original el 18 de febrero de 2019.
  13. ^ abc Paul, Matthias R. (3 de abril de 2002). «[fd-dev] Ctrl+Alt+Del». freedos-dev . Archivado desde el original el 9 de septiembre de 2017 . Consultado el 9 de septiembre de 2017 .(NB. Menciona una serie de valores mágicos utilizados por BIOS compatibles con IBM PC (0000h, 1234h), administradores de memoria DOS como EMM386 (1234h) y cachés de disco como SMARTDRV (EBABh, BABEh) y NWCACHE (0EDCh, EBABh, 6756h).)
  14. ^ "El proceso de arranque del BIOS/MBR". Base de conocimiento de NeoSmart . 2015-01-25. Archivado desde el original el 2023-03-26 . Consultado el 2019-02-03 .
  15. ^ "Comunidad TI E2E: ¿Alguien sabe si las siguientes configuraciones se pueden realizar con la herramienta MCP CLI?". Texas Instruments . 2011-08-27. Archivado desde el original el 2022-10-07.
  16. ^ Poley, Josh (30 de septiembre de 2009). "Números mágicos: números enteros". Learn . Microsoft . Archivado desde el original el 28 de marzo de 2023.
  17. ^ Newcomer, Joseph M. (13 de octubre de 2001). "Gestión de mensajes: garantizar la unicidad". Developer Fusion . Archivado desde el original el 21 de abril de 2005. Consultado el 16 de noviembre de 2007 .
  18. ^ Osterman, Larry (21 de julio de 2005). "Los UUID solo son únicos si los generas..." Larry Osterman's WebLog - Confessions of an Old Fogey (Blog web de Larry Osterman: confesiones de un viejo cascarrabias ). MSDN. Archivado desde el original el 28 de marzo de 2023. Consultado el 16 de noviembre de 2007 .
  19. ^ "RFC 9562 - Identificadores universalmente únicos (UUID)". ietf.org . Mayo de 2024 . Consultado el 9 de agosto de 2024 .
  20. ^ "Implementación de subprogramas Java con versiones de la familia JRE en el complemento Java para Internet Explorer". Oracle . Archivado desde el original el 2022-11-30 . Consultado el 2023-03-28 .
  21. ^ "Instalación de GNU GRUB, Sección 3.4: Instalación del BIOS". Gnu.org . Archivado desde el original el 2023-03-15 . Consultado el 2014-06-26 .
  22. ^ Heddings, Lowell (3 de noviembre de 2014). «Números mágicos: los códigos secretos que los programadores ocultan en su PC». How-To Geek . Archivado desde el original el 26 de marzo de 2023. Consultado el 3 de octubre de 2017 .
  23. ^ Cavit, Doug (24 de abril de 2012). "Protección contra la reutilización de referencias a objetos obsoletos". Microsoft Secure . Archivado desde el original el 26 de julio de 2018. Consultado el 26 de julio de 2018 .
  24. ^ Boleyn, Erich Stefan (4 de abril de 1995). "Comentarios sobre la propuesta del 'estándar MultiBoot'". Uruk.org . Archivado desde el original el 26 de marzo de 2023.
  25. ^ abcdef "Nota técnica TN2151: Comprensión y análisis de los informes de fallos de las aplicaciones". Documentación para desarrolladores de Apple . 29 de enero de 2009. Archivado desde el original el 13 de diciembre de 2018.
  26. ^ abcdef Birkett, Andrew. "Componentes internos del montón CRT de depuración de Win32". Nobugs.org .
  27. ^ McNamara, Paul (19 de julio de 2012). "El código de Microsoft contiene la frase 'grandes tetas'... Sí, de verdad". Network World .
  28. ^ WebKit, The WebKit Open Source Project, 6 de enero de 2023 , consultado el 6 de enero de 2023
  29. ^ "AddressSanitizer - Preguntas frecuentes". GitHub . Consultado el 18 de mayo de 2022 .
  30. ^ "MANUAL DE REFERENCIA DEL PROGRAMADOR INTEL 80386". MIT .
  31. ^ Scheppner, Carolyn. "Guía de Amiga Mail Vol.2". Cataclysm.cx . Archivado desde el original el 18 de julio de 2011. Consultado el 20 de agosto de 2010 .
  32. ^ "Comprobación de error 0xDEADDEAD MANUALLY_INITIATED_CRASH1". Documentación de Microsoft . 19 de junio de 2023.
  33. ^ "La versión 14.0.1 de Safari se cierra inesperadamente".
  34. ^ "Especificación del árbol de dispositivos".
  35. ^ "strncat_s, _strncat_s_l, wcsncat_s, _wcsncat_s_l, _mbsncat_s, _mbsncat_s_l". Documentación de Microsoft . Consultado el 16 de enero de 2019 .
Obtenido de "https://es.wikipedia.org/w/index.php?title=Número_mágico_(programación)&oldid=1253009760"