Pada tahun 1989 Felix Lee, John Hayes dan Angela Thomas menulis tes Hacker berupa kuis dengan banyak lelucon orang dalam, seperti, “ Apakah Anda makan jamur lendir? ”
Saya mempertimbangkan seri berikut:
0015 Ever change the value of 4?
0016 ... Unintentionally?
0017 ... In a language other than Fortran?
Apakah ada anekdot khusus yang membuat angka "4" khusus dalam seri?
Apakah beberapa implementasi Fortran memungkinkan untuk mengubah nilai konstanta? Apakah ini mungkin dalam bahasa lain yang umum digunakan pada saat itu?
4
untuk5
dalam daftar bilangan bulat diinternir.4 = 5
itu mungkin.Jawaban:
Di masa lalu (1970-an dan sebelumnya) beberapa komputer tidak memiliki MMU (dan ini berlaku hari ini untuk mikrokontroler yang sangat murah).
Pada sistem seperti itu, tidak ada perlindungan memori sehingga tidak ada segmen baca-saja di ruang alamat , dan program kereta dapat menimpa konstanta (baik dalam memori data, atau bahkan di dalam kode mesin).
Para penyusun Fortran pada waktu itu mengeluarkan argumen formal dengan referensi . Jadi jika Anda melakukannya
CALL FUN(4)
danSUBROUTINE FUN(I)
tubuhnya berubahI
- misalnya dengan pernyataanI = I + 1
di tubuhnya, Anda dapat mengalami bencana, mengubah 4 menjadi 5 di pemanggil (atau lebih buruk).Ini juga berlaku pada mikrokomputer pertama seperti IBM PC AT asli dari tahun 1984, dengan MS-DOS
FWIW, saya sudah cukup tua untuk digunakan, sebagai remaja belasan pada awal 1970-an, komputer seperti: IBM1620 dan CAB500 (di museum: ini adalah komputer era 1960-an!). IBM1620 cukup menyenangkan: digunakan dalam tabel memori untuk penambahan dan perkalian (dan jika Anda menimpa tabel ini, kekacauan terjadi). Jadi tidak hanya Anda bisa menimpa 4, tetapi Anda bahkan bisa menimpa setiap penambahan 2 + 2 atau 7 * 8 perkalian di masa depan (tapi saya benar-benar lupa detail kotor ini sehingga bisa salah).
Hari ini, Anda mungkin menimpa kode BIOS dalam memori flash, jika Anda cukup gigih. Sedihnya, saya tidak merasakan kesenangan itu lagi, jadi saya tidak pernah mencoba. (Saya bahkan takut menginstal beberapa LinuxBios di motherboard saya).
Pada komputer saat ini dan sistem operasi yang melewati konstanta dengan referensi dan mengubahnya di dalam callee hanya akan memicu pelanggaran segmentasi , yang terdengar akrab bagi banyak pengembang C atau C ++.
BTW: menjadi nitpicking: menimpa 4 bukan masalah bahasa, tetapi implementasi.
sumber
gfortran
. Konstanta dimasukkan ke dalam segmen mereka dan diteruskan dengan referensi ke subrutin. Secara default, bagian konstan hanya-baca, sehingga kesalahan perlindungan memori membunuh program.Itu adalah efek samping yang tidak disengaja dari strategi evaluasi panggilan fungsi FORTRAN dalam kombinasi dengan optimasi kompiler yang salah.
FORTRAN II memperkenalkan fungsi dan subrutin yang ditentukan pengguna dengan argumennya yang disahkan oleh referensi . (Ya, saya tidak tahu. Mungkin itu lebih efisien daripada nilai kelulusan pada perangkat keras IBM saat itu.)
Biasanya, pass-by-reference berarti Anda harus melewati nilai-l (seperti variabel) alih-alih nilai-r. Tetapi para perancang FORTRAN memutuskan untuk membantu dan membiarkan Anda memberikan nilai-r sebagai argumen. Kompiler akan secara otomatis menghasilkan variabel untuk Anda. Jadi, jika Anda menulis:
kompiler akan mengonversi ini di belakang layar menjadi sesuatu seperti
Ada juga optimasi kompiler umum yang disebut "kumpulan literal", yang akan mengkonsolidasikan beberapa contoh dari konstanta numerik yang sama ke dalam variabel yang dihasilkan secara otomatis yang sama. (Beberapa bahasa dalam keluarga C membutuhkan ini untuk string literal.) Jadi, jika Anda menulis
ini akan diperlakukan seolah-olah demikian
yang tampaknya seperti hal yang masuk akal untuk dilakukan sampai Anda memiliki subprogram yang mengubah nilai parameternya.
Ledakan!
CALL SUBBAR(4)
mengubah nilai 4 dalam kumpulan literal ke 5. Dan kemudian Anda bertanya-tanya mengapaSUBBAZ
dengan asumsi Anda memberikannya 5 bukannya4
Anda benar-benar menulis dalam kode.Versi yang lebih baru dari Fortran mengurangi masalah ini dengan membiarkan Anda mendeklarasikan
INTENT
variabel sebagaiIN
atauOUT
, dan memberi Anda kesalahan (atau setidaknya peringatan) jika Anda memberikan konstanta sebagaiOUT
parameter.sumber
Dalam FORTRAN, ketika sebuah konstanta dilewatkan ke prosedur lain, itu tidak lagi dilindungi. Itulah yang mereka rujuk. Bahasa pemrograman populer lainnya dalam waktu yang sama adalah C dan Pascal yang tidak (dan masih belum) memiliki masalah ini. Mungkin ada bahasa pemrograman lama yang tidak saya sadari memiliki masalah yang sama.
sumber
.rodata
segmen read-only (seperti yang dilakukan oleh kompiler saat ini) mengubahnya tidak akan mengubah konstanta tetapi akan menyebabkan SEGV.