"कभी 4 का मूल्य बदलें?" - यह हेस-थॉमस क्विज़ में कैसे आया?


24

1989 में फेलिक्स ली, जॉन हेस और एंजेला थॉमस ने एक हैकर की परीक्षा में कई अंदरूनी चुटकुलों के साथ प्रश्नोत्तरी का रूप लेते हुए लिखा , " क्या आप कीचड़-सांचे खाते हैं? "

मैं निम्नलिखित श्रृंखला पर विचार कर रहा हूं:

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

क्या श्रृंखला में विशेष रूप से "4" संख्या बनाने वाला एक विशेष उपाख्यान है?

क्या कुछ फोरट्रान कार्यान्वयन ने स्थिरांक के मूल्य को संशोधित करने की अनुमति दी थी? क्या उस समय अन्य भाषाओं में यह संभव था?


2
अगर हम दूसरा सवाल यहाँ रखते हैं, तो विशेष रूप से उत्तरदाताओं को यह समझाने का ध्यान रखें कि आधुनिक भाषाओं में ऐसा व्यवहार क्यों मौजूद है (यानी इसके लिए कोई व्यावहारिक उपयोग हैं?)। उस ने कहा, यह भी एक उत्कृष्ट कोड गोल्फ सवाल के लिए करना होगा ।
यानि

8
संबंधित: एक प्रोग्राम लिखें जो 2 + 2 = 5 बनाता है । एक जावा और अजगर वहाँ की जगह उत्तर देता है 4के लिए 5प्रशिक्षु पूर्णांकों सूचियों में।
मार्टिज़न पीटर्स

5
और उस पेज पर एक टिप्पणी में कहा गया है कि आप फोरट्रान IV में शाब्दिक को फिर से परिभाषित कर सकते हैं; 4 = 5संभव था।
मार्टिगन पीटरर्स

7
और उस हैकर के परीक्षण लिंक के लिए धन्यवाद। आपने अब मुझे बूढ़ा होने के साथ-साथ इस सवाल पर 'हां' का जवाब देने के लिए कितनी बार भयभीत किया।
Martijn Pieters

5
मैंने एक बार फोरट्रान कार्यक्रम में निरंतर शून्य के मान को बदल दिया। नीचे ट्रैक करने के लिए यह एक बहुत मुश्किल बग था।
ब्रायन ओकले

जवाबों:


32

पुराने दिनों में (1970 और उससे पहले) कुछ कंप्यूटरों में कोई एमएमयू नहीं था (और यह बहुत सस्ते माइक्रोकंट्रोलर के लिए आज सच है)।

ऐसी प्रणालियों पर, स्मृति सुरक्षा नहीं होती है, इसलिए पता स्थान में कोई रीड-ओनली सेगमेंट नहीं होता है , और एक छोटी गाड़ी प्रोग्राम एक स्थिरांक (या तो डेटा मेमोरी में, या मशीन कोड के अंदर भी) को अधिलेखित कर सकता है।

उस समय के फोरट्रान संकलक ने संदर्भ द्वारा औपचारिक तर्क पारित किए । तो अगर आपने किया CALL FUN(4)और SUBROUTINE FUN(I)इसका शरीर बदल रहा है I- जैसे I = I + 1कि इसके शरीर में एक बयान के साथ , आप एक आपदा हो सकते हैं, 4 को कॉलर में 5 (या बदतर) में बदल सकते हैं।

यह एमएस-डॉस के साथ 1984 से मूल आईबीएम पीसी एटी जैसे पहले माइक्रो कंप्यूटर पर भी सच था

FWIW, मैं 1970 के दशक की शुरुआत में एक टीन एजर के रूप में उपयोग करने के लिए काफी पुराना हूं, ऐसे कंप्यूटर: IBM1620 और CAB500 (एक संग्रहालय में: ये 1960 के युग के कंप्यूटर हैं!)। IBM1620 काफी मजेदार था: इसका उपयोग परिवर्धन और गुणन के लिए मेमोरी टेबलों में किया जाता था (और यदि आपने इन तालिकाओं को ओवरवोट कर दिया, तो अव्यवस्थित हो गए)। इसलिए न केवल आप एक 4 को अधिलेखित कर सकते हैं, बल्कि आप प्रत्येक भविष्य 2 + 2 जोड़ या 7 * 8 गुणन को भी अधिलेखित कर सकते हैं (लेकिन मैं वास्तव में इन गंदे विवरणों को भूल गया था इसलिए गलत हो सकता है)।

आज, आप फ़्लैश मेमोरी में BIOS कोड को अधिलेखित कर सकते हैं, यदि आप पर्याप्त रूप से दृढ़ हैं। अफसोस की बात यह है कि मुझे वह मज़ा कभी नहीं आता, इसलिए मैंने कभी कोशिश नहीं की। (मैं अपने मदरबोर्ड पर कुछ LinuxBios स्थापित करने से भी डरता हूं)।

वर्तमान कंप्यूटरों और ऑपरेटिंग सिस्टमों पर संदर्भ द्वारा एक स्थिरांक गुजरना और इसे कैली के अंदर बदलना बस एक विभाजन उल्लंघन को भड़काएगा , जो कई सी या सी ++ डेवलपर्स से परिचित लगता है।

BTW: नाइटपैकिंग होना: ओवरराइटिंग 4 भाषा का विषय नहीं है, बल्कि कार्यान्वयन का है।


14
1620 का उपनाम CADET: ऐड नॉट, डोंट नॉट ट्राई भी था।
पीट बेकर

चाल अब भी लगभग दोहराया जा सकता है gfortran। कॉन्स्टेंट को उनके सेगमेंट में डाल दिया जाता है और एक सबरूटीन के संदर्भ में पास कर दिया जाता है। डिफ़ॉल्ट रूप से, स्थिर खंड केवल-पढ़ने के लिए है, इसलिए मेमोरी सुरक्षा त्रुटि प्रोग्राम को मार देती है।
निचे

7

यह एक गलत संकलक अनुकूलन के साथ संयोजन में FORTRAN के फ़ंक्शन कॉल मूल्यांकन रणनीति का एक अनजाने साइड इफेक्ट था।

FORTRAN II ने उपयोगकर्ता-परिभाषित कार्यों और उप-वृत्तों को संदर्भ द्वारा पारित उनके तर्कों के साथ पेश किया । (क्यों, मुझे नहीं पता। यह शायद उस समय के आईबीएम हार्डवेयर पर पास-बाय-वैल्यू से अधिक कुशल था।)

आम तौर पर, पास-दर-संदर्भ का मतलब है कि आपको आर-मान के बजाय एल-मान (एक चर की तरह) पास करना होगा। लेकिन फोरट्रान के डिजाइनरों ने मददगार होने का फैसला किया और आर-वैल्यू को तर्क के रूप में वैसे भी पारित कर दिया। संकलक स्वचालित रूप से आपके लिए एक चर उत्पन्न करेगा। तो, अगर आपने लिखा है:

CALL SUBFOO(X + Y, 4)

संकलक इसे पर्दे के पीछे कुछ इस तरह परिवर्तित करेगा

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

एक आम संकलक अनुकूलन भी था जिसे "शाब्दिक पूल" कहा जाता है, जो एक ही संख्यात्मक स्थिर के कई उदाहरणों को एक ही ऑटो-जनरेट चर में समेकित करेगा। (सी परिवार की कई भाषाओं में इसके लिए स्ट्रिंग लिटरल की आवश्यकता होती है।) इसलिए, यदि आपने लिखा है

CALL SUBBAR(4)
CALL SUBBAZ(4)

यह माना जाएगा जैसे कि यह थे

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

जब तक कि आपके पास एक ऐसा सबप्रोग्राम होने के लिए एक पूरी तरह से उचित चीज की तरह लगता है जो अपने मापदंडों के मूल्य को बदलता है।

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

बूम! CALL SUBBAR(4)शाब्दिक पूल में 4 के मूल्य को 5. में बदल दिया और फिर आप सोच रहे हैं कि क्यों SUBBAZमान लिया गया है कि आपने इसे 4वास्तव में कोड में लिखे जाने के बजाय इसे 5 पास कर दिया है ।

फोरट्रान के नए संस्करण की अनुमति देकर इस समस्या को कम आप यह घोषणा INTENTके रूप में एक चर के INया OUT, और आपको एक त्रुटि दे रही है (या कम से कम एक चेतावनी) यदि आप एक के रूप में एक निरंतर पारित OUTपैरामीटर।


5

फोरट्रान में, जब एक स्थिरांक को दूसरी प्रक्रिया में पारित किया जाता है, तो इसे संरक्षित नहीं किया जाता है। यह वही है जो वे संदर्भित करते हैं। उसी समय की अन्य लोकप्रिय प्रोग्रामिंग भाषाएं सी और पास्कल थीं जो इस मुद्दे पर नहीं थीं (और अभी भी नहीं हैं)। हो सकता है कि पुरानी प्रोग्रामिंग लैंग्वेज हैं, जिनके बारे में मुझे पता नहीं है कि एक ही मुद्दा है।


इसके अलावा, यह इस तथ्य को संदर्भित करता है कि स्थिर पूल केवल-पढ़ने के लिए खंड में नहीं था। यदि यह किया गया था, और 4 संदर्भ द्वारा पारित किया गया है, और कैली द्वारा बदल दिया गया है, तो SEGV सफलतापूर्वक 4 परिवर्तन किए बिना होगा
बेसिल स्टायरनेविच

ऐसा इसलिए है क्योंकि प्रत्येक OS में केवल-पढ़ने वाला खंड नहीं था। उदाहरण के लिए, DOS का उपयोग DOS पर किया जा सकता है, रीड-ओनली सेगमेंट (वर्चुअल मेमोरी का उपयोग करके) के साथ ऑपरेटिंग सिस्टम जैसे UNIX रन टाइम में सेगमेंटेशन फॉल्ट एरर देगा। वैसे भी, कंपाइलर को इसकी अनुमति नहीं देनी चाहिए।
डीजे बजी विज्जी

4
मुझे पास्कल की याद आती है :(
गैरेथ

1
अधिक विशिष्ट होने के लिए, फोरट्रान संदर्भ से गुजरता है। इसलिए यदि आप फ़ंक्शन पैरामीटर के रूप में एक स्थिरांक पास करते हैं, तो आप उस संख्या के हर उपयोग के लिए उस मूल्य को बदल सकते हैं।
गेब

1
केवल तभी यदि वह स्थिरांक (संदर्भ द्वारा पारित) एक रीड-राइट सेगमेंट में रहता है। यदि यह .rodataकेवल पढ़ने वाले सेगमेंट में है (जैसा कि वर्तमान संकलक करते हैं) तो इसे बदलने से स्थिरांक नहीं बदलेगा, लेकिन एक SEGV का कारण होगा।
बेसिल स्टारीनेविच
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.