El lenguaje de programación C es un lenguaje muy bueno, pero antiguo. Es uno de los primeros lenguajes de programación de alto nivel que apareció en aquellos años.
Un desbordamiento en C es una cosa peligrosa que nos puede pasar si desarrollamos en este lenguaje.
Hoy veremos qué es un desbordamiento de una variable en C, cosa que es un poco peligrosa en apps que estén en producción.
Por cierto, esto se refiere a cuando una variable se desborda; pero puede que quieras ver un ejemplo de desbordamiento de búfer en C; algo que es un poco más peligroso.
Primero debemos saber los límites de los tipos de datos en C. Los más comunes son el int
o el float
, sin embargo debemos saber los límites de cada uno.
El tipo de dato int
con signo, al menos en las computadoras modernas, va desde -2147483648
hasta 2147483647
. El límite superior termina en 7 y no en 8 debido a que el cero también cuenta.
En cambio, un tipo de dato int
sin signo (de forma que no podemos representar números negativos) va desde 0
hasta 4294967295
.
¿Y cómo sabemos esto? bueno, todo depende del almacenamiento que ocupen las variables. Los enteros ocupan 4 bytes. 1 byte tiene 8 bits, por lo tanto 4 bytes son 32 bits.
En un entero con signo, ocupamos 31 bits para almacenar el número y 1 bit para el signo (menos – o más +); teniendo entonces 31 bits para nuestro número.
Como los números binarios son en base 2, tenemos que el límite es 2 elevado a la potencia 31, lo cual es 2,147,483,648 menos 1 porque también debemos representar el cero, o sea que tenemos un 2,147,483,647.
Y para el negativo sí tenemos hasta -2,147,483,648.
Pero, en un entero sin signo ocupamos los 32 bits completos, porque no usamos el signo. Y eso nos permite doblar el valor que tenemos con los 31 bits.
Para ser precisos, nos da hasta 4,294,967,296 menos 1, porque recordemos que el cero cuenta, así que al final tenemos 4, 294, 967, 295.
Si quieres más información busca en Google sobre los límites de los tipos de datos o visita este link que yo recomiendo, aunque con esto ya te habrás hecho una idea.
Recuerdo que la primera vez que pensé esto me sentí muy “mala onda” porque dije… oh, ¿qué harás ahora, C? ¿qué harás si a un entero que esté en su máximo punto le sumo 1, explotas? porque la primera vez que uno lo hace no sabe nada de matemáticas, ni bits, ni procesadores, ni arquitecturas ni álgebra booleana.
Pero bueno, ya en serio, ¿qué pasa?
#include <stdio.h>
int main(){
int numero = 2147483647;
printf("El numero, sin modificar es %d\n", numero);
numero = numero + 1; // O numero++
printf("El numero, despues de aumentarle 1 es %d\n", numero);
return 0;
}
Compilamos y ejecutamos…
Bueno, evidentemente la computadora no explotó porque sigo escribiendo esto (y tampoco pasó nada la primera vez que lo hice), simplemente la variable se desbordó.
Al aplicar la operación a nivel de memoria, el entero se reinició a su otro límite, el cual es -2, 147, 483, 648
.
Si hubiéramos sumado 2
, entonces se habría ido a -2, 147, 483, 647
y así sucesivamente.
Para un entero sin signo pasa lo mismo…
#include <stdio.h>
int main(){
unsigned int numero = 4294967295;
printf("El numero, sin modificar es %u\n", numero);
numero = numero + 1; // O numero++
printf("El numero, despues de aumentarle 1 es %u\n", numero);
return 0;
}
Compilamos y ejecutamos con la siguiente salida:
El numero, sin modificar es 4294967295
El numero, despues de aumentarle 1 es 0
En este caso, como es sin signo, de su límite ya no pasa a un negativo, sino al 0. Y si le hubiésemos aumentado 2, entonces se habría ido a 1, y así sucesivamente.
Tal vez no le veamos importancia, pero sí la tiene. No se me ocurre un ejemplo de la vida real en el que haya visto por mí mismo lo que pasa, pero podemos hacer suposiciones.
¿Qué pasa si tenemos los puntos de un usuario en un entero sin signo? supongamos que esos puntos le dan una ventaja a la hora de usar nuestro sistema, y aquel usuario que tenga más puntos tiene permiso de entrar.
Si un usuario (de alguna forma) gana muchos puntos (legalmente, porque es un buen usuario) hasta desbordar la memoria, su puntuación se reseteará.
O también podemos poner un ejemplo de un sistema embebido, sobre todo en aquellos que tienen una memoria muy pequeña. Ahí los desbordamientos son más comunes.
Esos son ejemplos supuestos, pero por ahí debe haber ejemplos de la vida real. Con estos que puse ya puedes pensar lo que ocasionaría un desbordamiento de memoria.
Por cierto, los desbordamientos también pasan en las restas. Si restamos y restamos, al final iremos a dar hasta el límite superior.
¿Mi consejo? investiga bien los límites de las variables, haz validaciones y pruebas para saber cómo se comportan tus sistemas en diferentes situaciones.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.
Ver comentarios