Recientemente en el desarrollo de uno de nuestros proyectos para iOS bajo Adobe Air nos encontramos con unos de esos casos inexplicables que sufrimos los programadores, y por los que podemos proclamar a los cuatro vientos que nuestra profesión apesta… (y no hemos podido evitar dejaros este genial vídeo XD)
¿Qué opinaríais de una aplicación que funciona al publicarla para testeo y desarrollo, y exactamente el mismo código falla al publicarla para distribución?… Pues ahí nos hemos visto envueltos…
Como es habitual en estos casos de poltergeist, después de perder mucho tiempo de nuestras miserables vidas haciendo pruebas y más pruebas, aislamos el motivo del cuelgue, que era un código tan malvado como un clásico bucle while como el que os mostramos (y que obviamente de provocador de cuelgues tiene poco…)
var i:int; var len:int; var index:int = -1; var data_arr:Array = new Array("one","two","three","four","five"); var foundIt:Boolean; const FOUND_NUMBER:String = "four"; foundIt= false; i=0; len = data_arr.length; while(i<len && foundIt==false) { if(data_arr[i] == FOUND_NUMBER) { foundIt= true; index= i; } else { i++; } }
¿Por qué la vida ha sido tan cruel de hacernos dar con este bug? No tiene ningún motivo lógico para que al publicar para distribución esto se ejecute de forma indefinida y cuelgue la aplicación, pero durante las pruebas salió a la luz la triste realidad que nos mostraba como la variable foundIt no se actualizaba correctamente dentro de la condición if, lo que hacia que nunca se saliera de bucle ya que la condición se cumplía, pero no se activaba la condición de salida…
Lo más sorprendente de todo es que lo que variaba el comportamiento del código era el modo de publicación, así que para determinar si era un BUG generalizado (no nos podíamos creer que eso no lo hubiéramos encontrado antes) realizamos pruebas más simples con la misma estructura de bucle. Pruebas en las que la variable foundIt se actualizaba correctamente y la aplicación tanto en desarrollo como en distribución no se quedaba colgada. Pero… no era suficiente para humillarnos… porque encima si metíamos un trace dentro del bucle para obtener el valor de la variable… funcionaba!
Esto nos lleva a un BUG aun más miserable… ya que no se reproduce en todas las circunstancias… por lo que nos decantamos a pensar que es un caso «particular» que se da bajo condiciones de una programación específica (este código iba en métodos de clases que heredaban de otras clases que… bueno ya sabéis…), cuando el compilador de Air codifica el código as3 para iOS (basado en LLVM).
En nuestro caso, la solución obvia y directa que aplicamos fue eliminar la segunda condicion de salida referida a foundIt del bucle while y emplear el propio contador que recorre el bucle para emigrar… quedando de la siguiente forma:
var i:int; var len:int; var index:int = -1; var data_arr:Array = new Array("one","two","three","four","five"); const FOUND_NUMBER:String = "four"; i=0; len = data_arr.length; while(i<len) { if(data_arr[i] == FOUND_NUMBER) { index= i; i = len; } else { i++; } }
Aunque en el fondo no resolvamos nada y posiblemente nunca se os reproduzca este bug, creímos que era necesario mencionarlo en este blog para:
- Recordarnos esto de por vida
- Compensar y dar algún sentido a semejante despropósito y cantidad de tiempo perdido con él
- Compartirlo con los demás que siempre ayuda a superar los traumas…