Una fuente frecuente de errores en programación

A lo largo de mis años como profesor de estructuras de información me he encontrado con mucha frecuencia con un tipo de error de programación que resulta difícil de detectar. Trataré de describir el error a través de un ejemplo real. Esta mañana revisaba en el laboratorio con uno de nuestros técnicos la respuesta a unos experimentos sobre similitud en colecciones de video digital. Una de las tareas consistía en localizar, dentro de una colección de vectores multidimensionales, los k vectores más próximos a uno dado (un algoritmo típico de búsqueda de vecinos). El programa escrito en C++ implementa la búsqueda mediante una estructura de Va-file (Vector Approximation File). El código que implementa esta búsqueda estaba convenientemente testado y respondió correctamente en todos los experimentos realizados hasta la fecha. Sin embargo, esta mañana sobre una de las colecciones de vectores, el programa generaba una respuesta incorrecta. En este caso, el Va-file se construía sobre un total de 33 millones de vectores, cifra sensiblemente superior a las que habíamos utilizado en experimentos previos.

Mi primera reacción ante el error fue revisar el tipo de dato que utilizaba el programa para direccionar tal cantidad de registros, pensando que posiblemente la cifra de 33 millones superaba el límite del valor máximo que la variable podría representar. No era así, pues la variable utilizada para almacenar el identificador de posición de los vectores era un entero con signo de 32 bits (-2.147.483.648 <= X <= 2.147.483.647). Sin embargo, cuando se necesita acceder de forma directa a la posición de un vector en el archivo, hay que efectuar un direccionamiento al byte de comienzo de dicho vector (esto se hace a través de la función seek o fseek), por lo que se precisa multiplicar la posición del vector p (0 <= p <= 33.000.000) por el tamaño en bytes de dicho vector (en nuestro caso 512).El valor máximo que se obtiene en esta operación es de 16.896.000.000, que desborda un tipo entero, incluso sin signo de 32 bits.

Este suele ser un error bastante frecuente en programación y me lo encuentro repetidamente en las soluciones a las prácticas de muchos de mis alumnos. Una posible solución es elegir un tipo de coma flotante (float, double o incluso long double) pero en nuestro caso la función fseek que utilizamos requiere un tipo entero como parámetro, por lo que optamos por direccionar el archivo en diferentes tramos, calculando el tramo al que pertenece el vector al que deseamos acceder e ir «saltando» tramo a tramo hasta el tramo indicado y una vez allí hasta el vector deseado. El programa finalmente aportó la respuesta correcta.

En general cuando se escribe código resulta muy «saludable»  prestar atención a las limitaciones en la cantidad o el orden de magnitud de los datos que es capaz de tratar nuestro programa y dejarlo reflejado en el código. Pero como la documentación de los programas suele ser una asignatura pendiente de la mayoría de programadores, cuando nos encontramos con respuestas inesperadas, apuntar a este tipo de errores suele dar buenos resultados. A mi al menos me lo ha dado.

Hasta otra.

Acerca de barrena

Bienvenidos a este diario, semanario, mensuario o como quiera que se desee denominar a este espacio donde intento comunicar los hechos más relevantes de mi actividad académica.
Esta entrada fue publicada en Software. Guarda el enlace permanente.

1 respuesta a Una fuente frecuente de errores en programación

  1. Alex dijo:

    Es decir, aprender de los errores ANOTANDO su análisis y posterior (re)solución, y no simplemente pasándolos cuanto antes y ya está… sería lo aprendido, ¿no amigo?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *