La verdadera respuesta aquí es: nunca se puede saber con certeza.
Al menos, para casos no triviales, no puede estar seguro de haberlo recibido todo. Considere lo siguiente del artículo de Wikipedia sobre código inalcanzable :
double x = sqrt(2);
if (x > 5)
{
doStuff();
}
Como Wikipedia señala correctamente, un compilador inteligente puede detectar algo como esto. Pero considere una modificación:
int y;
cin >> y;
double x = sqrt((double)y);
if (x != 0 && x < 1)
{
doStuff();
}
¿El compilador captará esto? Tal vez. Pero para hacer eso, tendrá que hacer más que correr sqrt
contra un valor escalar constante. Tendrá que descubrir que (double)y
siempre será un número entero (fácil), y luego comprender el rango matemático de sqrt
para el conjunto de enteros (difícil). Un compilador muy sofisticado podría hacer esto para la sqrt
función, o para cada función en math.h , o para cualquier función de entrada fija cuyo dominio pueda resolver. Esto se vuelve muy, muy complejo, y la complejidad es básicamente ilimitada. Puede seguir agregando capas de sofisticación a su compilador, pero siempre habrá una forma de introducir un código que será inalcanzable para cualquier conjunto de entradas.
Y luego están los conjuntos de entrada que simplemente nunca se ingresan. Entrada que no tendría sentido en la vida real, o quedaría bloqueada por la lógica de validación en otro lugar. No hay forma de que el compilador sepa sobre eso.
El resultado final de esto es que, si bien las herramientas de software que otros han mencionado son extremadamente útiles, nunca sabrás con certeza que capturaste todo a menos que revises el código manualmente después. Incluso entonces, nunca estarás seguro de que no te perdiste nada.
La única solución real, en mi humilde opinión, es estar lo más alerta posible, usar la automatización a su disposición, refactorizar donde pueda y buscar constantemente formas de mejorar su código. Por supuesto, es una buena idea hacer eso de todos modos.