Comportamiento indefinido

Un comportamiento indefinido (undefined behavior en inglés) en programación se refiere a la operación cuyo comportamiento es arbitrario. En los lenguajes de programación en los que se han definido comportamientos indefinidos las implementaciones pueden asumir que las operaciones que provocan un comportamiento indefinido nunca ocurren. Esta suposición hace válidas varias transformaciones del programa o simplifica las pruebas de validez dándole flexibilidad a la implementación del lenguaje. Es responsabilidad del programador escribir código que nunca invoque comportamientos indefinidos, pero la implementación del lenguaje tiene permitido mostrar mensajes de diagnóstico cuando esto suceda.

La existencia de comportamientos indefinidos le permite al lenguaje omitir algunas comprobaciones como (en el caso de C) que el divisor no sea 0 o que el resultado de una suma de enteros sin signo no sea mayor al máximo valor admitido por ese tipo de enteros sin signo. Esto ahorra algunos ciclos del procesador cada vez que esas operaciones son invocadas y asigna la responsabilidad de hacer esas comprobaciones cuando sean relevantes al programador.

Los efectos de la invocación de una operación que provoque un comportamiento indefinido pueden variar dependiendo de la arquitectura del procesador en la que se ejecute el programa, el cambio en cualquiera de los elementos de la cadena de herramientas (como el compilador), el sistema operativo, el contenido de la memoria, el momento de ejecución, etc.

Entre los posibles efectos de la invocación de un comportamiento indefinido está la ejecución esperada del programa (lo que oculta el problema), el cierre inesperado del programa, corrupción de la memoria, resultados incorrectos, fallo irrecuperable del sistema informático, vulnerabilidades de seguridad, etc.

Los comportamientos indefinidos no deben ser confundidos con los comportamientos no especificados o los comportamientos definidos por la implementación.

Comportamiento indefinido en C

Los comportamientos indefinidos en C únicamente son aquellos que son definidos como tales en el estándar ISO/IEC 9899 cuya última versión es ISO/IEC 9899:2011

Los compiladores pueden definir el comportamiento de determinadas operaciones que normalmente tienen un comportamiento indefinido por medio de opciones de compilación, por ejemplo Clang y GCC permiten el uso de la opción -fwrapv para que en caso de un desbordamiento de entero con signo este de la vuelta ("wrap around") véase desbordamiento de enteros. Los compiladores también pueden tener opciones para alertar sobre la ocurrencia de comportamientos indefinidos en tiempo de compilación o terminar el programa si sucede en tiempo de ejecución; en el caso de desbordamiento de enteros con signo GCC tiene la opción -ftrapv que termina el programa.

Ejemplos
Esta lista de ejemplos no es exhaustiva por lo que muchos casos de comportamientos indefinidos no están incluidos.

Operaciones aritméticas
Desbordamiento de enteros con signo
#include <limits.h> //Contiene macros con los valores minimos y maximos de los enteros

int main(int argc, char *argv[]){
  int numero;
  numero = INT_MAX; //INT_MAX es el valor máximo que se le puede asignar a un entero.
  numero += 1; //Desbordamiento de entero con signo
}

Enlaces externos
 Undefined Behavior: What Happened to My Code?
 What Every C Programmer Should Know About Undefined Behavior #1/3
 A Guide to Undefined Behavior in C and C++, Part 1