C
Ini mengingatkan saya pada kesalahan yang saya alami ketika saya belajar C. Sayangnya varian aslinya tampaknya tidak bekerja dengan GCC saat ini, tetapi yang ini masih:
#define ARR_SIZE 1234
int main() {
int i = ARR_SIZE;
int arr[ARR_SIZE];
while(i >= 0) {
(--i)[arr] = 0;
}
i = *(int*)0;
}
Ini jelas segfaults karena kita merujuk pointer nol, kan?
Salah - sebenarnya, ini adalah loop tak terbatas karena kondisi loop kami dimatikan satu per satu. Karena penurunan awalan, i
berjalan dari 1023 ke -1. Ini berarti tugas menimpa tidak hanya semua elemen dalam arr
, tetapi juga lokasi memori langsung sebelum itu - yang kebetulan merupakan tempat di mana i
disimpan. Pada saat mencapai -1
, i
menimpa dirinya sendiri 0
dan dengan demikian kondisi loop terpenuhi lagi ...
Ini adalah varian asli I yang tidak dapat saya reproduksi lagi:
Hal yang sama bekerja dengan i
naik dari 0 dan dimatikan oleh satu. GCC terbaru selalu disimpan i
sebelumnya arr
dalam memori; ini pasti berbeda di versi yang lebih lama (mungkin tergantung pada perintah deklarasi). Itu adalah kesalahan aktual yang saya hasilkan di salah satu program mainan pertama saya yang berurusan dengan array.
Juga, yang ini jelas jika Anda tahu bagaimana pointer bekerja di C, tetapi bisa mengejutkan jika Anda tidak:
Anda mungkin berpikir bahwa tugas untuk (--i)[arr]
melempar kesalahan, tetapi valid dan setara dengan arr[--i]
. Ekspresi a[x]
hanyalah gula sintaksis *(a + x)
yang menghitung dan merujuk pointer ke elemen yang diindeks; penambahan ini tentu saja komutatif dan dengan demikian setara dengan *(x + a)
.