109
Przy używaniu tablic trzeba być szczególnie ostrożnym przy konstruowaniu pętli, ponieważ ani kompilator, ani skompilowany program nie będą w stanie wychwycić przekroczenia przez indeks rozmiaru tablicy 1. Efektem będzie odczyt lub zapis pamięci, znajdującej się poza tablicą.
Wystarczy pomylić się o jedno miejsce (tzw. błąd off by one) by spowodować, że działanie programu zostanie nagle przerwane przez system operacyjny:
int foo[100]; int i;
for (i«0; i<-100; ++i) /• powinno być i<100 */ foo[i] = 0;
W pierwszej edycji konkursu IOCCC zwyciężył program napisany w C. który wygląda! dość nietypowo:
short mainD ■ {
277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800,
-113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004,
14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9,
4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419,
0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0,
4, 0, 0, 0, 0x8, 0, 4, 0, V, 0, 12, 0, 4, 0,
0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712,
’p\ 072163, ’r\ 29303 , 29801, 'e*
Co ciekawe program ten bez przeszkód wykonywał się na komputerach VAX-łl oraz PDP-11. Cały program to po prostu tablica z zawartym wewnątrz kodem maszynowym! Tak naprawdę jest to wykorzystanie pewnych właściwości programu, który ostatecznie produkuje kod maszynowy. Linkcr (to o nim mowa) nie rozróżnia na dobrą sprawę nazw funkcji od nazw zmiennych, więc bez problemu ustawił punkt wejścia programu na tablicę wartości, w których zapisany był kod maszynowy'. Tak przygotowany program został bez problemu wykonany przez komputer.
'W zaradzić kompilatory mają możliwość dodania takiego sprawdzania, ale nie robi się tego. gdyż znacznie (Spowolniłoby to działanie programu. Takie postępowanie jc*t jednak pożądane w okresie testowania programu.