2012-09-13 15 views
5

जब मैं संकलित करता हूं तो यह त्रुटि क्यों नहीं दे रहा है?जब मैं सरणी के अंत से परे लिखता हूं तो मुझे सेगमेंटेशन गलती क्यों नहीं मिलती?

#include <iostream> 
using namespace std; 

int main() 
{ 
    int *a = new int[2]; 
    // int a[2]; // even this is not giving error 
    a[0] = 0; 
    a[1] = 1; 
    a[2] = 2; 
    a[3] = 3; 
    a[100] = 4; 
    int b; 

    return 0; 
} 

कोई यह समझा सकता है कि यह क्यों हो रहा है। अग्रिम धन्यवाद।)

+4

दुर्भाग्यवश, परिभाषित व्यवहार ** कभी-कभी ** अपरिभाषित व्यवहार का सबसेट है :( – Mahesh

+0

@ माहेश :)) नहीं। –

+1

@LuchianGrigore ** कभी-कभी ** – Mahesh

उत्तर

2

मुझे लगता है कि आप जावा या जावा जैसी भाषा से आ रहे हैं, जहां एक बार जब आप किसी सरणी की सीमा से बाहर निकलते हैं, तो आपको "सीमाओं से बाहर सरणी अनुक्रमणिका" अपवाद मिलता है।

खैर, सी आपके से अधिक अपेक्षा करता है; यह आपके द्वारा मांगी जाने वाली जगह को बचाता है, लेकिन यह देखने के लिए जांच नहीं करता है कि क्या आप उस सहेजी गई जगह की सीमा से बाहर जा रहे हैं या नहीं। एक बार जब आप उपरोक्त वर्णित करते हैं, तो कार्यक्रम में उस अपरिभाषित व्यवहार से डर लगता है।

और भविष्य के लिए याद रखें कि यदि आपके प्रोग्राम में कोई बग है और आप इसे नहीं ढूंढ पा रहे हैं, और जब आप कोड/डीबग पर जाते हैं, तो सब कुछ ठीक लगता है, एक अच्छा मौका है कि आप ' फिर से "सीमा से बाहर" और एक आवंटित जगह तक पहुंच।

9

क्योंकि अपरिभाषित व्यवहार == कुछ भी हो सकता है। आप दुर्भाग्यपूर्ण हैं कि यह क्रैश नहीं होता है, इस तरह के व्यवहार संभावित रूप से बग को छुपा सकते हैं।

a के लिए दो बार परिभाषित किया जा रहा है - यह संकलक में एक बग है।

+0

मुझे खेद है। "ए" दो बार घोषित नहीं किया गया था। मैं बस कहना चाहता था कि दोनों घोषणाएं समान व्यवहार कर रही हैं। – singingsingh

+0

@singingsingh ठीक है :) तो दूसरे अनुच्छेद की उपेक्षा करें। –

8

a नामक दो चर घोषित करना निश्चित रूप से एक त्रुटि है; अगर आपका कंपाइलर इसे स्वीकार करता है, तो यह टूट गया है। मुझे लगता है कि आप का मतलब है कि यदि आप एक घोषणा को दूसरे के साथ बदलते हैं तो आपको अभी भी कोई त्रुटि नहीं मिलती है।

ऐरे पहुंच सीमा-जांच नहीं है। संकलन समय पर, किसी सरणी का आकार अक्सर ज्ञात नहीं होता है, और भाषा को तब भी चेक की आवश्यकता नहीं होती है जब यह हो। रन टाइम पर, एक चेक प्रदर्शन को कम कर देगा, जो सी ++ दर्शन के खिलाफ होगा जो आपको जिस चीज की आवश्यकता नहीं है उसके लिए भुगतान नहीं करेगा। इसलिए किसी सरणी के अंत से परे पहुंच अपरिभाषित व्यवहार प्रदान करती है, और यह सुनिश्चित करने के लिए प्रोग्रामर पर निर्भर करता है कि ऐसा नहीं होता है।

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

यदि आप सुरक्षित होना चाहते हैं, तो आप std::vector का उपयोग कर सकते हैं, और केवल at() फ़ंक्शन का उपयोग करके अपने तत्वों तक पहुंच सकते हैं। यह इंडेक्स की जांच करेगा, और अगर यह सीमा से बाहर है तो अपवाद फेंक देगा। यह आपके उदाहरण में मेमोरी रिसाव को ठीक करने के लिए आपके लिए स्मृति आवंटन भी प्रबंधित करेगा।

+0

मुझे खेद है। "ए" दो बार घोषित नहीं किया गया था। मैं बस कहना चाहता था कि दोनों घोषणाएं समान व्यवहार कर रही हैं। – singingsingh

0

अच्छे कोड विश्लेषण वाले कंपाइलर्स निश्चित रूप से आपके सरणी आवंटन से परे उस कोड संदर्भ पर चेतावनी देंगे। एकाधिक घोषणाओं को भूलना, यदि आप इसे चलाते हैं, तो यह गलती हो सकती है या नहीं (अपरिभाषित व्यवहार जैसा कि दूसरों ने कहा है)। यदि, उदाहरण के लिए, यदि आप उस पृष्ठ के बाहर नहीं लिखते हैं, तो आपको प्रोसेसर से कोई गलती नहीं मिलेगी, तो आपको ढेर का 4KB पृष्ठ (प्रोसेसर एड्रेस स्पेस में) मिला है। सरणी को हटाने पर, यदि आपने इसे किया है, और ढेर कार्यान्वयन के आधार पर, ढेर का पता लगा सकता है कि यह दूषित है।

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