2009-11-17 12 views
5

मुझे निम्नलिखित सी कोड में एक अजीब परिणाम मिल रहा है।malloc() और ढेर मेमोरी

int main() 
{ 
    int *p = (int *) malloc(100); 
    p[120] = 5; 
    printf("\n %d", p[120]); 
} 

चूंकि मैंने केवल 100 बाइट आवंटित किए हैं, इसलिए इस कोड को सेगमेंटेशन गलती होनी चाहिए। हालांकि, यह '5' प्रिंट करता है और कोई रनटाइम त्रुटि नहीं देता है। क्या कोई कारण बता सकता है?

+4

शायद भाग्यशाली हो गया। –

+5

आपने एक ऐसे स्थान पर 5 लिखा था जो आपके नहीं था। अगर उस जगह के मालिक को यह पसंद नहीं आया कि आपने अपने घर में क्या किया है, तो इसका बदला लिया जाएगा। ** सावधान रहें **, यह आपके यूएसबी डिस्क ड्राइवर से संबंधित हो सकता है और यह आपके द्वारा डाले गए अगले ड्राइव को प्रारूपित करेगा। – pmg

+4

@pmg: वास्तव में, यह आधुनिक संरक्षित-मोड ऑपरेटिंग सिस्टम पर बहुत अधिक संभावना नहीं है। – bcat

उत्तर

20

नहीं, कोड (अनिवार्य रूप से) एक segfault देना नहीं चाहिए। एक segfault तब होता है जब आप किसी वर्चुअल मेमोरी पेज तक पहुंचने का प्रयास करते हैं जो आपकी प्रक्रिया में आवंटित नहीं है।

"हीप" या "फ्री स्टोर" आपकी प्रक्रिया के स्वामित्व वाले वर्चुअल मेमोरी पेजों का एक क्षेत्र है। malloc() एपीआई इस क्षेत्र को ब्लॉक में विभाजित करता है और ब्लॉक में एक सूचक देता है।

यदि आप उस ब्लॉक के अंत से बाहर हैं जहां आपके पास पॉइंटर है, तो आप आम तौर पर ढेर का हिस्सा हैं, लेकिन आपके आवंटित ब्लॉक का हिस्सा नहीं हैं। इस तरह, आप ढेर को परिभाषित करने के लिए malloc() उपयोग करने वाले अन्य ढेर ब्लॉक या यहां तक ​​कि डेटा संरचनाओं को भी दूषित कर सकते हैं।

Writing Solid Code: Microsoft's Techniques for Developing Bug-Free C Programs by Steve Maguire alt text http://ecx.images-amazon.com/images/I/5148TK6JCVL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg

पंडिताऊ के लिए एक परिशिष्ट: दुर्लभ मामलों में

ढेर भ्रष्टाचार पर अधिक जानकारी के लिए, और अपने कोड की डिबग संस्करण में यह पता लगाने के लिए तरीकों के लिए, यह एक महान किताब है , ढेर ब्लॉक के अंत से परे स्मृति तक पहुंचकर, आप उस मेमोरी तक पहुंच सकते हैं जो ढेर का हिस्सा नहीं है। इन मामलों में, आपको अपेक्षित सेगमेंटेशन गलती मिल सकती है। आप ढेर की तुलना में कुछ अन्य डेटा संरचना भी दूषित कर सकते हैं। यह वास्तव में मौका का मामला है। हालांकि, ढेर खुद ही सामान्य ढेर ब्लॉक की तुलना में बहुत बड़ा है, इसलिए आपके उदाहरण जैसे 99% समय कोड ढेर को भ्रष्ट कर देगा। आपके द्वारा प्रदान किया गया उदाहरण उस 99% मामले में आता है।

+0

दरअसल, चूंकि उन्होंने ढेर के अंत से 20 बाइट्स बदलने के लिए कहा, आर्किटेक्चर और आस-पास के कोड के आधार पर वह स्टैक को नली बना सकता है, या प्रोग्राम को भी बदल सकता है। व्यवहार वास्तव में अपरिभाषित है। –

+2

टी.ई.डी. यह केवल "तरह का" सत्य है। वर्चुअल मेमोरी पेज आकार वाले मशीन का उपयोग करने में कोई संदेह नहीं है। संभावित रूप से निष्पादन योग्य कोड में ढेर की तुलना में अलग-अलग वीएम सुरक्षा होती है। मैं डरता हूं कि वह इस तरह की प्रणाली पर है क्योंकि सी मानक लाइब्रेरी malloc() फ़ंक्शन मौजूद है। जो भी आप लिखते हैं वह सच है, हालांकि, विशेष रूप से रेडियो शैक मॉडल III पर जेड -80 पर टीआरएस-डॉस चल रहा है। ;) –

+0

और हाँ, यहां तक ​​कि एक वीएम पृष्ठ प्रणाली पर, जो भी आप लिख सकते हैं वह संभव हो सकता है। यह संभवतः ऐसा नहीं है और यह उस विवरण में जाने के लिए बहुत ही व्यावहारिक नहीं है जो शायद ही कभी मायने रखता है। जिस स्तर पर कहा गया है उस स्तर पर समस्या का समाधान करें। पैडेंट्री से बचें। –

0

आप स्मृति में लिख रहे हैं जिसे आपने आवंटित नहीं किया है। अंततः प्रोग्राम ढेर भ्रष्टाचार के प्रभावों के कारण समाप्त हो सकता है यदि इसका रन टाइम पर्याप्त लंबा था।

6

अवैध मेमोरी एक्सेस हमेशा सेगमेंटेशन गलती, बस त्रुटि या अन्य क्रैश का कारण नहीं बनती है। उदाहरण के लिए, यदि आपके सरणी के तुरंत बाद आवंटित एक और ब्लॉक है, तो आप में मान बदल रहे हैं कि ब्लॉक - जो कुछ भी हो सकता है।

0

आप अनियमित स्मृति को लिख रहे हैं; सी में इसकी अनुमति है, यह सिर्फ एक अच्छा विचार नहीं है। इस तरह की चीज जरूरी नहीं है कि विभाजन खंड हो।

+2

"अनुमति" शब्द का आपका उपयोग भ्रामक है। यह वाक्य रचनात्मक रूप से मान्य है, लेकिन अपरिभाषित व्यवहार का आह्वान करता है। –

3

नहीं, यह एक segfault दे सकता है, लेकिन केवल अगर स्मृति आपकी प्रक्रिया से बाहर है। अन्यथा यह आपके प्रोग्राम मेमोरी के कुछ अन्य क्षेत्र को संशोधित करेगा। सी इसके लिए जांच नहीं करता है, या उपरोक्त जैसे स्पष्ट मामलों में भी आपको किसी भी तरह से सुरक्षित नहीं करता है। कई सॉफ़्टवेयर क्रैकर्स सी के इस "फीचर" का उपयोग अनिवार्य रूप से ऐसे प्रोग्राम को फिर से लिखने के लिए करते हैं, जिसने निजीकृत किया है, और स्वयं को अपनी मशीन पर नियंत्रण दें। इसे buffer overflow exploit कहा जाता है।

यही कारण है कि सी (और सी ++) को वास्तव में नए सॉफ्टवेयर के लिए एडा जैसे सुरक्षित भाषाओं के लिए प्राथमिकता से बचा जाना चाहिए।

+1

मुझे पता है कि आखिरी वाक्य मुझे नकारात्मक वोट देगा। मुझे परवाह नहीं है यह सच है। मेरे द्वारा –

+0

+1। मैं पूरी तरह से सहमत। – lesscode

0

विभाजन गलती के सामान्य कारण:

  • अमान्य मान
  • अपसंदर्भन अशक्त संकेत
  • एक में लिखने के लिए प्रयास कर रहा रीड-ओनली खंड
  • मुक्त-इंग अनुचित संकेत या संयुक्त राष्ट्र के साथ अपसंदर्भन सूचक प्रसिद्ध ब्लॉक

    int * x = 0;

    x = 200;/ कारणों विभाजन गलती */

segfaults क्या एक अवैध स्मृति का उपयोग निर्धारित किया जाता है के आधार पर MMU अपवाद द्वारा उत्पन्न कर रहे हैं। ओएस कैसे इसकी स्मृति को संरचित करता है, इस पर निर्भर करता है कि ओएस पर एक मेमोरी एक्सेस कानूनी हो सकती है (हालांकि गलत) और किसी अन्य ओएस पर यह अवैध हो सकता है।

+0

यह साल देर हो चुकी है, लेकिन ... x = 200 ठीक है, * x = 200 segfault की ओर जाता है। –

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