2013-08-23 16 views
36

कोड के निम्न भाग में, *(int32 *) 0 = 0; का अर्थ क्या है?इसका क्या अर्थ है ?: * (int32 *) 0 = 0;

void 
function (void) 
{ 
    ... 

    for (;;) 
    *(int32 *) 0 = 0;  /* What does this line do? */ 
} 

कुछ नोट:

  • कोड, पहुंच योग्य नहीं हो रहा है के रूप में वहाँ कोड के उस विशेष टुकड़ा से पहले एक निकास बयान है।
  • int32typedef 'ed है लेकिन आपको इसके बारे में बहुत अधिक परवाह नहीं करना चाहिए।
  • कोड का यह टुकड़ा किसी भी व्यक्ति के लिए किसी कंपाइलर में किसी भाषा के रनटाइम से है।
+7

यह एक अनंत लूप है जो शून्य के 4 बाइट्स को 0-3 स्थानों में संग्रहीत करता है। यह एक जानबूझकर गर्भपात या जानबूझकर लटका की तरह दिखता है। –

+2

@ हाबीब हां संभोग मुझे पता है कि '(;;)' एक अनंत लूप है। नीचे का टुकड़ा वह है जिसे मैं समझ नहीं पा रहा हूं। अस्पष्टता के लिए खेद है। – NlightNFotis

+0

@ कर्टिस मुझे नहीं लगता कि यह एक बुरी बात है। यह अनुभवी कंपाइलर इंजीनियरों द्वारा लिखा गया है, और यह एक कारण के लिए होना चाहिए। कुछ गलत होने के मामले में असामान्य निष्पादन एक व्यावहारिक कारण की तरह लगता है, अब तक जवाब दिए गए हैं। – NlightNFotis

उत्तर

32

कोड निम्नलिखित कार्य कर रही:

for (;;) // while(true) 
    *(int32 *) 0 = 0; // Treat 0 as an address, de-reference the 0 address and try and store 0 into it. 

यह SEGFAULT चाहिए, नल पॉइंटर de-संदर्भ।

संपादित

संकलित और अधिक जानकारी के लिए भाग गया:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 

int main(void){ 
    *(int32_t *) 0 = 0; 
    printf("done\n"); 
    return 0; 
} 

gcc -g null.c; ./a.out

Program received signal SIGSEGV, Segmentation fault. 
0x00000000004004cd in main() at null.c:7 
7   *(int32_t *) 0 = 0; 
+3

@ ऋषि: किसी भी उचित प्रणाली पर (शायद कुछ बहुत छोटे एम्बेडेड प्लेटफॉर्म के लिए छोड़कर), गलती केवल उस कार्यक्रम को प्रभावित करेगी। –

+0

@ किथ थॉम्पसन मैंने सोचा कि ऑपरेटिंग सिस्टम मेमोरी में निचले पतों में एक पॉइंटर टेबल को अपने दिनचर्या में स्टोर करेगा? क्या यह अब आधुनिक ऑपरेटिंग सिस्टम में सच नहीं है? – Hrishi

+25

@ ऋषि: मुझे कोई जानकारी नहीं है - लेकिन किसी भी आधुनिक बहु-प्रोसेसिंग ओएस (यूनिक्स, लिनक्स, विंडोज़, ...) पर, एक अप्रकाशित प्रोग्राम ओएस-स्तरीय डेटा संरचनाओं को भ्रष्ट नहीं कर सकता है (जब तक कि ओएस पर कोई बग न हो, लेकिन इस तरह के एक बग इस तरह के मामूली कोड से ट्रिगर होने की संभावना नहीं है)। आमतौर पर प्रत्येक प्रक्रिया का अपना वर्चुअल एड्रेस स्पेस होता है; आपकी प्रक्रिया के लिए पता 0, यदि यह मौजूद है, तो कर्नेल के लिए या किसी अन्य प्रक्रिया के लिए पता 0 के साथ कुछ लेना देना नहीं है। –

3

यह अपरिभाषित व्यवहार का एक अनंत लूप है (एक अशक्त सूचक dereferencing)। यह * एन * एक्स पर एक segfault या विंडोज पर एक्सेस उल्लंघन के साथ दुर्घटनाग्रस्त होने की संभावना है।

6

for(;;)while(1) के बराबर है,

*(int32 *) 0 = 0; एक dereferenced नल पॉइंटर है, जो एक दुर्घटना का कारण होने की संभावना है करने के लिए 0 लिखते हैं, लेकिन वास्तव में नहीं होगा कुछ compilers पर हर समय: Crashing threads with *(int*)NULL = 1; problematic?

3

माइक टिप्पणी बहुत अच्छी तरह से सही है: यह ADDRESS 0.

पर VALUE शून्य संग्रहीत कर रहा है जो अधिकांश मशीनों पर एक क्रैश होगा।

22

वास्तव में है कि इस कोड SEG-दोषयुक्त कारण है कि यह है की व्याख्या नहीं करता मौजूद है =)

मुझे लगता है कि कुछ MCU के क्रम से है .. और कारण यह है क्योंकि अगर प्रोग्राम निष्पादन इस बात इस तरह के लिए मिल जाएगा निर्देश या तो एमसीयू के लिए सॉफ़्टवेयर रीसेट शुरू करेगा, इसलिए प्रोग्राम को पुनरारंभ किया जाएगा (जो एम्बेडेड विकास में सामान्य प्रथा है) या यदि एमसीयू हार्डवेयर वॉचडॉग के साथ कॉन्फ़िगर किया गया है, तो हार्डवेयर निगरानी के कारण एमसीयू पुनरारंभ करें और कभी भी अंतराल लूप न करें।

ऐसे निर्माणों का मुख्य लक्ष्य एक बाधा उत्पन्न करने के लिए जिसे ओएस या हार्डवेयर द्वारा कुछ क्रियाओं को शुरू करने के लिए संभाला जा सकता है।

यह जानकर कि इसका x86 यह एक सीपीयू मोड पर निर्भर करेगा ... असली मोड में वास्तव में कुछ भी नहीं होगा अगर कोई निगरानी नहीं है, तो पता 0 पर 'विभाजित 0' हैंडलर का पता है, इसलिए यदि यह है कुछ पुराने एमएस-डॉस या एम्बेडेड x86 रनटाइम यह 'डिवाइड बाय 0' हैंडलर से 0 तक का पता बदल देंगे, जैसे ही ऐसा होता है और इस बाधा को मुखौटा नहीं किया जाता है, सीपीयू स्थान 0: 0 पर कूद जाएगा और शायद बस पुनरारंभ होगा अवैध निर्देश के कारण ..यदि यह संरक्षित है या वीएम x86 कोड है तो यह ओएस या किसी अन्य पर्यवेक्षक को सूचित करने का एक तरीका है कि रनटाइम में कोई समस्या है और सॉफ़्टवेयर को बाहरी रूप से 'मार' दिया जाना चाहिए।

+0

स्पष्टीकरण दोस्त के लिए धन्यवाद! हालांकि यह x86- लक्षित कोड है और कभी निष्पादित नहीं लगता है। कोड के उस विशेष भाग से पहले 'बाहर निकलें (0)' है, और मेरा मानना ​​है कि अगर बाहर निकलने के साथ कुछ गड़बड़ है तो उसे रोकना है। – NlightNFotis

+0

आप सही हैं, – evilruff

+0

अपडेट किया गया उत्तर धन्यवाद, जो मेरे सिद्धांत की पुष्टि करता है :) – NlightNFotis

26

ओपी राज्यों कोड अनुभवी संकलक इंजीनियरों द्वारा लिखा गया था के बाद से, यह संभव है इस कोड के इरादे है:

  • *(int32 *) 0 = 0; कोड के रूप में इस विशिष्ट सी कार्यान्वयन का कारण बनता है कि व्यवहार द्वारा परिभाषित नहीं द्वारा मान्यता प्राप्त है सी मानक और इस कार्यान्वयन के लिए अवैध होने के लिए जाना जाता है।
  • for (;;) अतिरिक्त रूप से इंगित करता है कि यह कोड कभी बाहर नहीं निकला है।
  • कंपाइलर इंजीनियरों को पता है कि अनुकूलक इस कोड को पहचान लेगा और यह समझ जाएगा कि इसे "अनुकूलित किया जा सकता है", क्योंकि इस कोड तक पहुंचने वाला कोई भी प्रोग्राम किसी भी व्यवहार की अनुमति देता है, इसलिए अनुकूलक इसे व्यवहार देने का विकल्प चुन सकता है अगर कोड कभी नहीं पहुंचा है। यदि आप एक सी कार्यान्वयन के आंतरिक आपरेशन के विशिष्ट ज्ञान

तर्क इस तरह की संभव केवल है। यह एक प्रकार का कंपाइलर इंजीनियर हो सकता है सी कार्यान्वयन के लिए विशेष शीर्षलेखों में शामिल हो सकता है, शायद उस निश्चित कोड को चिह्नित करने के लिए (जैसे abort कॉल के बाद कोड) कभी नहीं पहुंचता है। इसे सामान्य प्रोग्रामिंग में कभी भी इस्तेमाल नहीं किया जाना चाहिए।


उदाहरण के लिए, इस कोड पर विचार करें:

if (a) 
    for (;;) 
     *(int 32 *) 0 = 0; 
else 
    foo(); 

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

if (a) 
    foo(); 
else 
    foo(); 

और आगे के लिए सरल किया जा सकता:

foo(); 
1

यह हो सकता है कि संकलक पता नहीं है exit() वापस नहीं करता है, लेकिन यह जानते हैं कि यह निर्माण नहीं करता है वापसी।

3

मूल IBM PC stored the interrupt vector table in the lowest 1 KiB of memory। इसलिए वास्तव में इस तरह के एक आर्किटेक्चर पर पता 0 पर 32-बिट मान लिखना INT 00h के लिए पते को ओवरराइट करेगा। INT 00h looks unused in the PC.

मूल रूप से कुछ भी आधुनिक (x86 में अर्थ/x86-64 parlace कुछ भी संरक्षित या लंबे मोड में चल रहा) पर, यह एक विभाजन गलती जब तक आप अंगूठी 0 (कर्नेल मोड) में हैं ट्रिगर किया जाएगा क्योंकि आप कर रहे हैं आपकी प्रक्रिया के बाहर कदम उठाने 'अनुमत पता dereference रेंज।

जैसा कि अव्यवस्था अपरिभाषित व्यवहार है (जैसा कि पहले से कहा गया है), एक सेगमेंटेशन गलती उस स्थिति को संभालने का एक पूरी तरह से स्वीकार्य तरीका है। यदि आप जानते हैं कि लक्षित आर्किटेक्चर पर एक शून्य पता dereference सेगमेंटेशन गलती का कारण बनता है, तो यह एप्लिकेशन को क्रैश करने के लिए एक बहुत ही निश्चित तरीका प्रतीत होता है। यदि exit() रिटर्न देता है, तो संभवतः आप जो करना चाहते हैं, क्योंकि कुछ बहुत ही गलत हो गया है।यह कोड किसी विशेष कंपाइलर के रनटाइम से है जिसका मतलब है कि जो भी इसे लिखा है, वह कंपाइलर और रनटाइम के आंतरिक कार्यों के ज्ञान का लाभ उठा सकता है, साथ ही विशिष्ट लक्ष्य आर्किटेक्चर के व्यवहार के अनुरूप भी हो सकता है।

+1

00h डॉस पर शून्य इंटरप्ट द्वारा विभाजित किया गया था। (http://en.wikipedia.org/wiki/BIOS_interrupt_call) मुझे संदेह है कि यहां क्या हो रहा है, हालांकि। –

संबंधित मुद्दे