stringtranslate.com

Variable no inicializada

En informática , una variable no inicializada es una variable que se declara pero no se le asigna un valor conocido definido antes de su uso. Tendrá algún valor, pero no uno predecible. Como tal, es un error de programación y una fuente común de errores en el software.

Ejemplo del lenguaje C

Una suposición común que hacen los programadores novatos es que todas las variables se establecen en un valor conocido, como cero, cuando se declaran. Si bien esto es cierto para muchos lenguajes, no lo es para todos ellos, por lo que existe la posibilidad de error. Los lenguajes como C utilizan el espacio de pila para las variables, y la colección de variables asignadas para una subrutina se conoce como marco de pila . Si bien la computadora reservará la cantidad adecuada de espacio para el marco de pila, generalmente lo hace simplemente ajustando el valor del puntero de pila y no establece la memoria en sí misma en ningún nuevo estado (generalmente por cuestiones de eficiencia). Por lo tanto, cualquier contenido de esa memoria en ese momento aparecerá como valores iniciales de las variables que ocupan esas direcciones.

He aquí un ejemplo sencillo en C:

void count ( void ) { int k , i ; para ( i = 0 ; i < 10 ; i ++ ) { k = k + 1 ; } printf ( "%d" , k ); }                         

El valor final de kno está definido. La respuesta de que debe ser 10 supone que comenzó en cero, lo que puede ser cierto o no. Tenga en cuenta que en el ejemplo, la variable ise inicializa en cero mediante la primera cláusula de la fordeclaración.

Otro ejemplo puede ser cuando se trabaja con estructuras . En el fragmento de código a continuación, tenemos una struct studentque contiene algunas variables que describen la información sobre un estudiante. La función register_studentpierde contenido de memoria porque no logra inicializar completamente los miembros de struct student new_student. Si observamos más de cerca, al principio, se inicializan age, semestery student_number. Pero la inicialización de los miembros first_namey last_namees incorrecta. Esto se debe a que si la longitud de las matrices de caracteres first_namey last_namees menor a 16 bytes, durante strcpy, [1] no logramos inicializar completamente los 16 bytes completos de memoria reservados para cada uno de estos miembros. Por lo tanto, después de memcpy()'ing la estructura resultante a output, [2], perdemos algo de memoria de pila al llamador.

struct student { unsigned int edad ; unsigned int semestre ; char nombre [ 16 ]; char apellido [ 16 ]; unsigned int numero_de_estudiante ; };               int register_student ( struct student * output , int age , char * first_name , char * last_name ) { // Si alguno de estos punteros es nulo, fallamos. if ( ! output || ! first_name || ! last_name ) { printf ( "Error! \n " ); return -1 ; }                      // Nos aseguramos de que la longitud de las cadenas sea menor a 16 bytes (incluido el byte nulo) // para evitar desbordamientos if ( strlen ( first_name ) > 15 || strlen ( last_name ) > 15 ) { printf ( "first_name y last_name no pueden tener más de 16 caracteres! \n " ); return -1 ; }               // Inicializando los miembros struct student new_student ; new_student . age = age ; new_student . weekly = 1 ; new_student . student_number = get_new_student_number (); strcpy ( new_student . first_name , first_name ); strcpy ( new_student . last_name , last_name );                  //copiando el resultado a la salida memcpy ( output , & new_student , sizeof ( struct student )); return 0 ; }      

En cualquier caso, incluso cuando una variable se inicializa implícitamente con un valor predeterminado como 0, normalmente no es el valor correcto . Inicializado no significa correcto si el valor es uno predeterminado. (Sin embargo, la inicialización predeterminada a es una práctica correcta para punteros y matrices de punteros, ya que los hace inválidos antes de que realmente se inicialicen con su valor correcto). En C, las variables con duración de almacenamiento estático que no se inicializan explícitamente se inicializan a cero (o nulo, para punteros). [3]

Las variables no inicializadas no sólo son una causa frecuente de errores, sino que este tipo de error es particularmente grave porque puede no ser reproducible: por ejemplo, una variable puede permanecer sin inicializar sólo en alguna rama del programa. En algunos casos, los programas con variables no inicializadas pueden incluso pasar las pruebas de software .

Impactos

Las variables no inicializadas son errores muy peligrosos, ya que pueden aprovecharse para filtrar memoria arbitraria, sobrescribir la memoria de forma arbitraria o ejecutar código, según el caso. Cuando se explota un software que utiliza la aleatorización del diseño del espacio de direcciones (ASLR), a menudo es necesario conocer la dirección base del software en la memoria. La explotación de una variable no inicializada de forma que se obligue al software a filtrar un puntero de su espacio de direcciones se puede utilizar para evitar la ASLR.

Uso en idiomas

Las variables no inicializadas son un problema particular en lenguajes como el lenguaje ensamblador, C y C++ , que fueron diseñados para la programación de sistemas . El desarrollo de estos lenguajes implicó una filosofía de diseño en la que los conflictos entre el rendimiento y la seguridad generalmente se resolvían a favor del rendimiento. El programador tenía la responsabilidad de estar al tanto de cuestiones peligrosas como las variables no inicializadas.

En otros lenguajes, las variables suelen inicializarse con valores conocidos cuando se crean. Algunos ejemplos son:

Incluso en lenguajes donde se permiten variables no inicializadas, muchos compiladores intentarán identificar el uso de variables no inicializadas y los informarán como errores de tiempo de compilación . Algunos lenguajes ayudan en esta tarea ofreciendo construcciones para manejar la inicialización de las variables; por ejemplo, C# tiene un estilo especial de parámetros de llamada por referencia a subrutinas (especificados como en lugar del habitual ), afirmando que se permite que la variable no esté inicializada en la entrada pero se inicializará después.outref

Véase también

Referencias

  1. ^ cuerda
  2. ^ memcpy()
  3. ^ "ISO/IEC 9899:TC3 (estándar C actual)" (PDF) . 2007-09-07. p. 126 . Consultado el 26 de septiembre de 2008 .Artículo 6.7.8, párrafo 10.
  4. ^ "Especificación del lenguaje Java: 4.12.5 Valores iniciales de las variables". Sun Microsystems . Consultado el 18 de octubre de 2008 .

Lectura adicional