Une différence fondamentale entre C et Java réside dans le fait que si on évite certaines fonctionnalités facilement identifiables de Java (par exemple, celles de l' Unsafe
espace de noms), toute action possible, y compris les actions "erronées" - aura un nombre limité de résultats possibles. . Bien que cela limite ce que l’on puisse faire en Java - du moins sans utiliser l’ Unsafe
espace de nom, cela permet également de limiter les dommages pouvant être causés par un programme erroné ou - plus important encore - par un programme qui traiterait correctement fichiers valides, mais n'est pas particulièrement protégé contre les fichiers erronés.
Traditionnellement, les compilateurs C traitaient de nombreuses actions de la manière définie par la norme dans les cas "normaux", tout en traitant de nombreux cas critiques "d'une manière caractéristique de l'environnement". Si vous utilisiez un processeur qui court-circuiterait et prendrait feu en cas de dépassement de capacité numérique et souhaitait éviter que le processeur ne prenne feu, il faudrait écrire du code pour éviter tout dépassement de capacité numérique. Si, toutefois, on utilisait un processeur qui tronquerait parfaitement les valeurs en complément de deux, on n'aurait pas à éviter les débordements dans les cas où une telle troncature entraînerait un comportement acceptable.
Le C moderne va encore plus loin: même si l’on cible une plate-forme qui définirait naturellement un comportement tel que le dépassement numérique où la norme n’imposerait aucune exigence, le dépassement d’une partie du programme peut affecter le comportement d’autres parties du programme. programme de manière arbitraire non liée par les lois du temps et de la causalité. Par exemple, considérons quelque chose comme:
uint32_t test(uint16_t x)
{
if (x < 50000) foo(x);
return x*x; // Note x will promote to "int" if that type is >16 bits.
}
Un compilateur C "moderne" à partir de ce qui précède pourrait conclure que puisque le calcul de x * x déborderait si x était supérieur à 46340, il pouvait effectuer l'appel de "foo" sans condition. Notez que même s'il serait acceptable qu'un programme se termine anormalement si x est en dehors de la plage, ou que la fonction retourne une valeur quelconque dans de tels cas, appeler foo () avec un x en dehors de la plage pourrait causer des dommages bien au-delà. l'une de ces possibilités. Le C traditionnel ne fournirait pas d’équipement de sécurité autre que celui fourni par le programmeur et la plate-forme sous-jacente, mais permettrait à l’équipement de sécurité de limiter les dommages résultant de situations inattendues. Le C moderne contournera tout équipement de sécurité qui ne serait pas efficace à 100% pour tout contrôler.