En informática , una variable no inicializada es una variable que se declara pero no se establece en un valor conocido definido antes de ser utilizada. Tendrá algún valor, pero no 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 hecha por 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 idiomas, no es cierto para todos ellos, por lo que existe la posibilidad de error. Los lenguajes como C usan espacio de pila para 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 la pila, generalmente lo hace simplemente ajustando el valor del puntero de la pila y no establece la memoria en ningún estado nuevo (generalmente por razones de eficiencia). Por lo tanto, cualquier contenido de esa memoria en ese momento aparecerá como valores iniciales de las variables que ocupan esas direcciones.
Aquí hay un ejemplo simple en C:
recuento de vacíos ( vacío ) { int k , i ; para ( i = 0 ; i < 10 ; i ++ ) { k = k + 1 ; } printf ( "% d" , k ); }
El valor final de k
no 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 i
se inicializa a cero mediante la primera cláusula de la for
declaración.
Otro ejemplo puede ser cuando se trata de estructuras . En el fragmento de código a continuación, tenemos un struct student
que contiene algunas variables que describen la información sobre un estudiante. La función register_student
pierde memoria porque no puede inicializar completamente los miembros de struct student new_student
. Si miramos más de cerca, al principio age
, semester
y student_number
se inicializan. Pero la inicialización de los miembros first_name
y last_name
es incorrecta. Esto se debe a que si la longitud de las matrices de caracteres first_name
y last_name
es inferior a 16 bytes, durante el strcpy
, no podemos inicializar completamente los 16 bytes completos de memoria reservados para cada uno de estos miembros. Por lo tanto, después memcpy()
de aplicar la estructura resultante a output
, filtramos algo de memoria de pila al llamador.
struct estudiante { unsigned int age ; semestre int sin firmar ; char first_name [ 16 ]; char last_name [ 16 ]; unsigned int student_number ; }; 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 inferior 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 . edad = edad ; new_student . semestre = 1 ; new_student . número_estudiante = get_new_student_number (); strcpy ( new_student . first_name , first_name ); strcpy ( nuevo_estudiante . apellido , apellido ); // copiando el resultado a la salida memcpy ( salida , & new_student , sizeof ( struct student )); return 0 ; }
En cualquier caso, incluso cuando una variable se inicializa implícitamente a un valor predeterminado como 0, este no suele ser el valor correcto . Inicializado no significa correcto si el valor es el predeterminado. (Sin embargo, la inicialización predeterminada a 0 es una práctica correcta para punteros y matrices de punteros, ya que los invalida antes de que se inicialicen realmente a 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). [1]
Las variables no inicializadas no solo 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 solo 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 poderosos, ya que pueden explotarse para filtrar memoria arbitraria o para lograr una sobrescritura de memoria arbitraria o para obtener la ejecución de código, según el caso. Cuando se explota un software que utiliza la distribución aleatoria del diseño del espacio de direcciones , a menudo se requiere conocer la dirección base del software en la memoria. La explotación de una variable no inicializada para obligar al software a filtrar un puntero de su espacio de direcciones se puede utilizar para omitir 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 rendimiento y seguridad se resolvieron generalmente a favor del rendimiento. Al programador se le dio la carga de estar al tanto de problemas peligrosos como las variables no inicializadas.
En otros lenguajes, las variables a menudo se inicializan a valores conocidos cuando se crean. Ejemplos incluyen:
- VHDL inicializa todas las variables estándar en un valor especial 'U'. Se utiliza en la simulación, para la depuración, para permitir al usuario saber cuando el no les importa los valores iniciales, a través de la lógica de varios valores , afecta a la salida.
- Java no tiene variables no inicializadas. Los campos de clases y objetos que no tienen un inicializador explícito y los elementos de las matrices se inicializan automáticamente con el valor predeterminado para su tipo (falso para booleano, 0 para todos los tipos numéricos, nulo para todos los tipos de referencia). [2] Las variables locales en Java deben asignarse definitivamente antes de acceder a ellas, o se trata de un error de compilación.
- Python inicializa las variables locales en
NULL
(distintas deNone
) y genera unUnboundLocalError
cuando se accede a dicha variable antes de ser (re) inicializada a un valor válido. - D inicializa todas las variables a menos que el programador especifique explícitamente que no lo haga.
Incluso en lenguajes donde se permiten variables no inicializadas, muchos compiladores intentarán identificar el uso de variables no inicializadas y reportarlas como errores en tiempo de compilación .
Ver también
Referencias
- ^ "ISO / IEC 9899: TC3 (estándar C actual)" (PDF) . 2007-09-07. pag. 126 . Consultado el 26 de septiembre de 2008 . Sección 6.7.8, párrafo 10.
- ^ "Especificación del lenguaje Java: 4.12.5 Valores iniciales de variables" . Sun Microsystems . Consultado el 18 de octubre de 2008 .
Otras lecturas
- CWE-457 Uso de variable no inicializada [1] .