Código inalcanzable

En programación, el código inalcanzable es una parte del código fuente que nunca podrá ser ejecutado porque no existe ningún camino dentro de las estructuras de control en el resto del programa para llegar a este código.[1]

Suele referirse a este tipo de código como código muerto, aunque entre ellos hay una diferencia (el código muerto se ejecuta pero no produce cambios en la salida del programa).[2]

El código inalcanzable generalmente se considera indeseable por las siguiente razones:

  1. Ocupa memoria innecesaria.
  2. Genera almacenamiento innecesario en la caché de instrucciones de la CPU - lo que también disminuye la localidad de datos.
  3. Desde la perspectiva de mantenimiento de software, se pierde tiempo y esfuerzo en mantener y documentar una pieza de código que nunca se ejecuta.

Causas editar

La existencia de código inalcanzable puede ser debido a varios factores, tales como:

  • Errores de programación en situaciones complejas de saltos condicionales.
  • Consecuencia de las transformaciones internas realizadas por un compilador optimizador.
  • Pruebas de software incompletas que no se pudo detectar código inalcanzable.
  • Código obsoleto que un programador se haya olvidado de borrar.
  • Código no utilizado que un programador haya decidido no suprimir, ya que estaba entremezclado con el código funcional.
  • Código condicionalmente útil que nunca será alcanzado, dado que los datos de entrada nunca causará que el código va a ser ejecutado.
  • Código complejo obsoleto que se retuvo intencionalmente, pero se dejó inalcanzable para que pueda ser utilizado más adelante en el desarrollo si es necesario.
  • Construcciones de depuración y vestigios de código durante el desarrollo que aún no se han retirado del programa.

En los últimos cinco casos, el código que es inalcanzable, a menudo existe como parte de un legado, es decir, código que una vez fue útil, pero ya no se utiliza o no se requiere. Sin embargo, el código inalcanzable también puede ser parte de un componente complejo (biblioteca, módulo o rutina), donde el código sigue siendo útil en conjunción con diferentes datos de entrada (nunca generada por la aplicación actual) o en condiciones que no se cumplen en el entorno de ejecución actual, haciendo el código correspondiente inalcanzable, pero puede ocurrir en otros entornos de ejecución, para que el componente no ha sido desarrollado.

Un ejemplo de tal código condicionalmente inalcanzable puede ser la implementación de una función printf() en la biblioteca de tiempo de ejecución de un compilador, el cual contiene el código complejo para procesar todos los argumentos de cadenas posibles, de los que en realidad es sólo un pequeño subconjunto utilizados en el programa. Sin tener que recompilar la biblioteca de ejecución, los compiladores normalmente no serán capaces de eliminar las secciones de código no utilizadas en tiempo de compilación.

Ejemplo editar

Considerando el siguiente código en C:

int foo (int X, int Y) {
  return X + Y;
  int Z = X*Y;
}

La definición de Z = X*Y nunca es alcanzada debido a que la función retorna el flujo del programa a la parte que la llamó antes, de esta manera dicha definición puede ser descartada.

Análisis editar

La detección de código inalcanzable es una forma de análisis estático y consiste en realizar un análisis de control de flujo para encontrar el código que nunca se ejecutará independientemente de los valores de las variables y otras condiciones en tiempo de ejecución. En algunos lenguajes (como Java[3]​) algunas formas de código inalcanzable no están permitidas y no es posible compilar el programa con este tipo de código. Se conoce a la optimización que remueve código inalcanzable como eliminación de código muerto (que es la misma para el código muerto y código redundante).

A veces el código puede volverse inalcanzable por alguna optimización introducida por el compilador como por ejemplo: eliminación de subexpresiones comunes.

En la práctica la sofisticación del análisis realizado tiene un impacto significativo en la cantidad de código inalcanzable que se detecta. Por ejemplo, el plegamiento de constantes y un simple análisis de control de flujo muestra que la declaración a = 2 en el siguiente código no se puede alcanzar:

 int N = 2 + 1;
 if (N == 4) {
   a = 2;
 }

Sin embargo se necesita más sofisticación para determinar si esta declaración a = 2 es o no inalcanzable debido que con un método tradicional habría que calcular la raíz cuadrada en tiempo de compilación:

 double d = sqrt(2);
 if (d > 5) {
   a = 2;
 }

Profiling editar

A veces se pueden utilizar profilers para detectar código inalcanzable, un profiler no prueba nada acerca de si el código realmente es o no inalcanzable pero es una buena heurística para buscar código potencialmente inalcanzable. Una vez detectado las partes potenciales se puede llevar a cabo en las mismas un análisis más profundo.

Véase también editar

Referencias editar

  1. Debray, S. K.; Evans, W.; Muth, R.; De Sutter, B. (marzo de 2000). «Compiler techniques for code compaction.» (PDF). Volume 22, issue 2 (en inglés). New York, USA: ACM Transactions on Programming Languages & Systems (TOPLAS). Bibcode:378-415. 
  2. «Eliminación de Código Inalcanzable y Código Muerto». 
  3. «Java Language Specification». 

Bibliografía editar

  • Muchnick S. S. 1997 Advanced Compiler Design and Implementation. Morgan Kaufmann.
  • Appel, A. W. 1998 Modern Compiler Implementation in Java. Cambridge University Press.

Enlaces externos editar