“4 değerini hiç değiştirmedin mi?” - Bu nasıl Hayes-Thomas sınavına girdi?


24

1989'da Felix Lee, John Hayes ve Angela Thomas, Hacker'ın sınavına birçok içeriden şaka yapan bir sınav yaptı. “ Balçık kalıpları yiyor musunuz?

Aşağıdaki seriyi düşünüyorum:

0015 Ever change the value of 4?
0016 ... Unintentionally?
0017 ... In a language other than Fortran?

Seride “4” sayısını belirten belirli bir fıkra var mı?

Bazı Fortran uygulamaları sabitlerin değerini değiştirmeye izin verdi mi? Bu, o sırada yaygın olarak kullanılan diğer dillerde mümkün mü?


2
@Ordous İkinci soruyu burada tutmamızın sakıncası yok, özellikle de cevaplayıcılar böyle bir davranışın neden modern dillerde olduğunu açıklamaya özen gösterirse (yani bunun için herhangi bir pratik kullanım var mı?). Bununla birlikte, mükemmel bir Code Golf sorusu olacağını da söyledi .
yannis

8
İlgili: 2 + 2 = 5 yapan bir program yazın . Bir Java ve Python orada yerini cevaplar 4için 5staj tamsayılar listelerinde.
Martijn Pieters

5
Ve bu sayfadaki bir yorum FORTRAN IV'deki değişmezleri yeniden tanımlayabileceğinizi; 4 = 5mümkündü.
Martijn Pieters

7
Hacker'in test bağlantısı için teşekkürler. Şimdi bana kendimi yaşlı hissettiriyor, ayrıca sorulara ne kadar sıklıkla 'evet' cevabını verebileceğim konusunda dehşete kapılmıştınız.
Martijn Pieters

5
Bir fortran programındaki sabit sıfırın değerini bir kez değiştirdim. İzini sürmek çok zor bir işti.
Bryan Oakley,

Yanıtlar:


32

Eski günlerde (1970'ler ve öncesi) bazı bilgisayarlarda MMU yoktu (ve bu çok ucuz mikrodenetleyiciler için bugün geçerlidir).

Bu tür sistemlerde, bellek koruması yoktur, bu nedenle adres alanında salt okunur bir bölüm yoktur ve bir buggy programı sabitin üzerine yazabilir (veri belleğinde veya makine kodunun içinde).

O sırada Fortran derleyicileri referans olarak resmi argümanlardan geçti . Yaptığın Yani eğer CALL FUN(4)ve SUBROUTINE FUN(I)değişen vücudunu vardır I- örneğin bir ifade ile I = I + 1kendi vücudunda, sen arayana (ya da kötü) içinde 5 içine 4 değiştirerek, bir felaket olabilir.

Bu aynı zamanda 1984’teki orijinal IBM PC AT gibi ilk mikrobilgisayarlarda MS-DOS ile de doğruydu.

FWIW, 1970'lerin başlarında genç bir yaşlı olarak, bu tür bilgisayarları kullanacak kadar yaşlandım: IBM1620 ve CAB500 (bir müzede: bunlar 1960'ların çağındaki bilgisayarları!). IBM1620 oldukça eğlenceliydi: toplama ve çarpma işlemleri için hafıza tablolarında kullanıldı (ve eğer bu tabloların üzerine yazarsanız, kaos ortaya çıktı). Bu yüzden, sadece 4'ün üzerine yazamazsınız, ancak gelecekteki her 2 + 2 ilavenin veya 7 * 8 çarpımın üzerine bile yazabilirsiniz (ancak bu kirli ayrıntıların gerçekten unutulduğundan yanlış olabilir).

Bugün, yeterince ısrar ediyorsanız, flash bellekteki BIOS kodunun üzerine yazabilirsiniz. Ne yazık ki, artık o kadar eğlenceli hissetmiyorum, bu yüzden hiç denemedim. (Hatta anakartıma bazı LinuxBios yüklemek korkuyorum).

Mevcut bilgisayarlarda ve işletim sistemlerinde referans olarak sabit geçen ve arayanın içinde değiştirmek sadece birçok C veya C ++ geliştiricisinin bildiği gibi segmentasyon ihlaline yol .

Btw: nitpicking olmak: 4 üzerine yazma, dil değil, uygulama meselesidir.


14
1620 takma CADET oldu: Ekleyemez, hatta denemez.
Pete Becker

Hile şimdi bile ile neredeyse tekrar edilebilir gfortran. Sabitler kendi bölümlerine yerleştirilir ve bir alt rutine referansla iletilir. Varsayılan olarak, sabit bölüm salt okunurdur, bu nedenle bellek koruma hatası programı öldürür.

7

Hatalı bir derleyici optimizasyonu ile birlikte FORTRAN'ın işlev çağrısı değerlendirme stratejisinin kasıtsız bir yan etkisi oldu.

FORTRAN II, kullanıcı tanımlı fonksiyonlar ve alt yordamları, referans olarak verilen argümanlarıyla tanıttı . (Neden, bilmiyorum. Muhtemelen zamanın IBM donanımı için değersiz değerden daha etkiliydi.)

Normal olarak, referans referansı, r değeri yerine bir l değerini (değişken gibi) iletmeniz gerektiği anlamına gelir. Ancak FORTRAN'ın tasarımcıları yardımcı olmaya karar verdi ve yine de r-değerlerini argüman olarak iletmenize izin verdi. Derleyici sizin için otomatik olarak bir değişken oluşturur. Yani, eğer yazdıysanız:

CALL SUBFOO(X + Y, 4)

derleyici bunu perde arkasındaki gibi bir şeye çevirirdi

TEMP1 = X + Y
TEMP2 = 4
CALL SUBFOO(TEMP1, TEMP2)

Aynı zamanda, aynı sayısal sabitin birden fazla örneğini aynı otomatik olarak üretilen değişkenle birleştiren “değişmez havuz” adı verilen ortak bir derleyici optimizasyonu da vardı. (C ailesindeki birkaç dilde bunun için çok sayıda dize gerekir.) Öyleyse, eğer yazdıysanız

CALL SUBBAR(4)
CALL SUBBAZ(4)

Bu sanki öyleymiş gibi muamele görürdü

FOUR = 4
CALL SUBBAR(FOUR)
CALL SUBBAZ(FOUR)

Bu , parametrelerinin değerini değiştiren bir alt program olana kadar yapılması makul bir şey gibi görünüyor .

SUBROUTINE SUBBAR(X)
    !...lots of code...
    X = 5
    !...lots of code...
END SUBROUTINE SUBBAR

Boom! CALL SUBBAR(4)değişmezlik havuzundaki 4'ün değerini 5 olarak değiştirdi ve sonra neden kodda yazdığınız SUBBAZyerine neden 5'i geçtiğinizi varsaydığınızı merak ediyorsunuz 4.

Fortran'ın daha yeni sürümleri, INTENTbir değişkeni INveya olarak tanımlamanıza izin OUTvererek ve bir sabit olarak OUTparametre olarak geçerseniz size bir hata (veya en azından bir uyarı) vererek, bu sorunu azaltır .


5

FORTRAN'da bir sabit başka bir işleme geçirildiğinde, artık korunmaz. Bahsettikleri şey bu. Aynı zamanda diğer popüler programlama dilleri, C ve Pascal idi ve bu sorunu hala yoktu (ve hala da yoktu). Belki de bunun farkında olmayan daha eski programlama dilleri vardır.


Ayrıca, sabit havuzun salt okunur bir segmentte olmadığı gerçeğini ifade eder. O yaptı ve 4 referans ile geçti ve tarafından Aranan değiştirilirse, SEGV olmadan olur başarıyla 4. değişen
Basile Starynkevitch

Çünkü her işletim sisteminin salt okunur bir bölümü yoktu. Örneğin, DOS'ta kullanılabilir; UNIX gibi salt okunur kesimli işletim sistemleri (sanal bellek kullanarak) çalışma zamanında bir segmentasyon hatası hatası verir. Neyse, derleyici buna izin vermemelidir.
dj bazzie wazzie

4
Pascal'ı özlüyorum :(
Gareth

1
Daha spesifik olmak gerekirse, FORTRAN başvuruya geçer. Böylece bir fonksiyon parametresi olarak bir sabit iletirseniz, bu sayının her kullanımında bu değeri değiştirebilirsiniz.
Gabe

1
Sadece bu sabit (referans ile iletilir) okuma-yazma segmentinde kalırsa. Bir ise .rodatasalt okunur segmentinde (mevcut derleyiciler gibi) sabit değiştirmez değiştirmeden ancak SEGV neden olur.
Basile Starynkevitch,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.