किसी सरणी को सीमा से बाहर ले जाना कितना खतरनाक है?


221

अपनी सीमा के बाहर (C) में किसी सरणी तक पहुँचना कितना खतरनाक है? यह कभी-कभी ऐसा हो सकता है कि मैं सरणी के बाहर से पढ़ता हूं (मुझे अब समझ में आया कि मैं अपने कार्यक्रम के कुछ अन्य हिस्सों या उससे भी परे उपयोग की जाने वाली मेमोरी का उपयोग करता हूं) या मैं सरणी के बाहर एक सूचकांक में मान सेट करने का प्रयास कर रहा हूं। कार्यक्रम कभी-कभी क्रैश हो जाता है, लेकिन कभी-कभी बस चलता है, केवल अप्रत्याशित परिणाम देता है।

अब मैं जानना चाहता हूं कि यह वास्तव में कितना खतरनाक है? यदि यह मेरे कार्यक्रम को नुकसान पहुंचाता है, तो यह इतना बुरा नहीं है। अगर दूसरी ओर यह मेरे कार्यक्रम के बाहर कुछ तोड़ता है, क्योंकि मैं किसी तरह कुछ पूरी तरह से असंबंधित स्मृति तक पहुंचने में कामयाब रहा, तो यह बहुत बुरा है, मैं कल्पना करता हूं। मैंने बहुत कुछ पढ़ा 'कुछ भी हो सकता है ’, might विभाजन कम से कम बुरी समस्या हो सकती है’ , hard आपकी हार्ड डिस्क गुलाबी हो सकती है और यूनिकॉर्न आपकी खिड़की के नीचे गाना हो सकता है ’, जो सब अच्छा है, लेकिन वास्तव में खतरा क्या है?

मेरे सवाल:

  1. क्या सरणी के बाहर के मूल्यों को पढ़ने से मेरे प्रोग्राम के अलावा कुछ भी नुकसान हो सकता है? मैं कल्पना करूंगा कि चीजों को देखने से कुछ भी नहीं बदलता है, या क्या यह उस फ़ाइल के 'अंतिम बार खोले गए' विशेषता को बदलने के लिए होगा, जो मैं करने के लिए हुआ था?
  2. क्या मेरे प्रोग्राम से अलग किसी भी चीज़ को नुकसान पहुंचाने के लिए वैल्यू सेट कर सकते हैं? इस स्टैक ओवरफ्लो प्रश्न से मैं इकट्ठा करता हूं कि किसी भी मेमोरी स्थान तक पहुंचना संभव है, कि कोई सुरक्षा गारंटी नहीं है।
  3. अब मैं XCode के भीतर से अपने छोटे प्रोग्राम चलाता हूं। क्या यह मेरे कार्यक्रम के आसपास कुछ अतिरिक्त सुरक्षा प्रदान करता है जहां यह अपनी स्मृति से बाहर नहीं पहुंच सकता है? क्या यह एक्सकोड को नुकसान पहुंचा सकता है?
  4. अपने अंतर्निहित छोटी गाड़ी कोड को सुरक्षित रूप से चलाने के बारे में कोई सिफारिशें?

मैं OSX 10.7, Xcode 4.6 का उपयोग करता हूं।


सामान्य तौर पर, ओएस आपकी खराबी से खुद को और अन्य प्रक्रियाओं की रक्षा करेगा। यह कुछ ऐसा नहीं है, जिस पर आप बहुत अधिक भरोसा करना चाहते हैं, हालाँकि।
गर्म चाट

7
इसके अलावा, आप अपनी हार्ड डिस्क पर किसी फ़ाइल तक पहुंचने के लिए कभी भी "नहीं पहुंचेंगे" जब सीमा और एक्सेस इंडेक्स सीमा से बाहर (आपके राम में)।
ड्रमर बी

1
मेरा मानना ​​है कि आप सी सरणी के बारे में पूछ रहे हैं, है ना? इसलिए ओजस्वी से इसका कोई लेना देना नहीं है और यह वास्तव में किसी भी आईडीई से संबंधित नहीं है।
ब्रायन चेन

17
यहाँ अजीब परिणामों का मेरा पसंदीदा उदाहरण है (यह स्टैक से संबंधित है, लेकिन मैंने पाया कि यह वास्तव में ज्ञानवर्धक है ...)।
phipsgabler

जवाबों:


125

जहाँ तक ISO C मानक (भाषा की आधिकारिक परिभाषा) का संबंध है, इसकी सीमा के बाहर एक सरणी तक पहुँचने का " अपरिभाषित व्यवहार " है। इसका शाब्दिक अर्थ है:

व्यवहार, एक गैर-योग्य या गलत कार्यक्रम के निर्माण या गलत डेटा के उपयोग पर, जिसके लिए यह अंतर्राष्ट्रीय मानक कोई आवश्यकता नहीं रखता है

एक गैर-मानक नोट इस पर फैलता है:

संभव अपरिभाषित व्यवहार, अप्रत्याशित परिणामों के साथ स्थिति को पूरी तरह से अनदेखा करने से लेकर, अनुवाद या कार्यक्रम के निष्पादन के दौरान व्यवहार करने के लिए पर्यावरण की एक प्रलेखित तरीके से विशेषता (एक नैदानिक ​​संदेश जारी किए बिना या बिना), अनुवाद या निष्पादन को समाप्त करने के साथ होता है। नैदानिक ​​संदेश का)।

तो वह सिद्धांत है। वास्तविकता क्या है?

"सर्वोत्तम" मामले में, आप कुछ मेमोरी को एक्सेस करेंगे जो या तो आपके वर्तमान में चल रहे प्रोग्राम के स्वामित्व में है (जो आपके प्रोग्राम को दुर्व्यवहार का कारण बन सकता है), या जो आपके वर्तमान में चल रहे प्रोग्राम के स्वामित्व में नहीं है (जो संभवतः आपके प्रोग्राम का कारण बनेगा एक खराबी की तरह कुछ के साथ दुर्घटना)। या आप स्मृति में लिखने का प्रयास कर सकते हैं जो आपके कार्यक्रम का मालिक है, लेकिन यह केवल पढ़ने के लिए चिह्नित है; यह संभवतः आपके प्रोग्राम को क्रैश करने का कारण भी बनेगा।

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

यहां तक ​​कि एक संरक्षित ओएस वातावरण में, सुरक्षा हमेशा 100% नहीं होती है। ऑपरेटिंग सिस्टम बग्स हैं जो रूट (प्रशासनिक) एक्सेस प्राप्त करने के लिए अप्रकाशित कार्यक्रमों की अनुमति देते हैं, उदाहरण के लिए। साधारण उपयोगकर्ता विशेषाधिकारों के साथ, एक खराबी कार्यक्रम अत्यधिक संसाधनों (सीपीयू, मेमोरी, डिस्क) का उपभोग कर सकता है, संभवतः पूरी प्रणाली को नीचे ला सकता है। बहुत सारे मैलवेयर (वायरस इत्यादि) सिस्टम पर अनधिकृत पहुँच प्राप्त करने के लिए बफर ओवररन का शोषण करते हैं।

(एक ऐतिहासिक उदाहरण: मैंने सुना है कि कुछ पुरानी प्रणालियों पर कोर मेमोरी के साथ , बार-बार एक तंग लूप में किसी एक मेमोरी लोकेशन तक पहुंचने का शाब्दिक कारण हो सकता है कि मेमोरी का हिस्सा पिघल जाए। अन्य संभावनाओं में सीआरटी डिस्प्ले को नष्ट करना, और रीड को स्थानांतरित करना शामिल है। / ड्राइव कैबिनेट के हार्मोनिक आवृत्ति के साथ एक डिस्क ड्राइव का सिर लिखें, जिससे यह एक टेबल के पार चल सकता है और फर्श पर गिर सकता है।)

और चिंता करने के लिए हमेशा स्काईनेट है।

लब्बोलुआब यह है: यदि आप जानबूझकर कुछ बुरा करने के लिए एक कार्यक्रम लिख सकते हैं , तो यह कम से कम सैद्धांतिक रूप से संभव है कि एक छोटी गाड़ी कार्यक्रम गलती से वही कर सकता है ।

व्यवहार में, यह बहुत कम संभावना नहीं है कि मैकॉज़ एक्स सिस्टम पर चलने वाला आपका छोटी गाड़ी प्रोग्राम क्रैश से अधिक गंभीर कुछ भी करने वाला है। लेकिन यह पूरी तरह से बुरा काम करने से छोटी गाड़ी कोड को रोकने के लिए संभव नहीं है ।


1
धन्यवाद, मैं वास्तव में इसे पूरी तरह से समझता हूं। लेकिन यह तुरंत एक अनुवर्ती प्रश्न को ट्रिगर करता है: एक शुरुआत प्रोग्रामर क्या कर सकता है, अपने कंप्यूटर को अपने स्वयं के संभवतः भयानक कृतियों से बचाने के लिए? जब मैंने किसी कार्यक्रम का पूरी तरह से परीक्षण कर लिया, तो मैं इसे दुनिया में फैला सकता हूं। लेकिन पहला ट्रायल रन एक गलत कार्यक्रम है। आप लोग अपने सिस्टम को खुद से कैसे सुरक्षित रखते हैं?
क्रिस डी

6
@ क्रिस: हम भाग्यशाली हो जाते हैं। 8-)} गंभीरता से, OS- स्तर की सुरक्षा इन दिनों बहुत अच्छी है। सबसे खराब स्थिति, अगर मैं एक आकस्मिक कांटा बम लिखता हूं, तो मुझे ठीक होने के लिए रिबूट करना पड़ सकता है। लेकिन सिस्टम को वास्तविक नुकसान शायद इस बारे में चिंता करने लायक नहीं है, जब तक कि आपका कार्यक्रम खतरनाक होने के किनारे पर कुछ करने की कोशिश नहीं कर रहा है। यदि आप वास्तव में चिंतित हैं, तो वर्चुअल मशीन पर प्रोग्राम चलाना एक बुरा विचार नहीं हो सकता है।
कीथ थॉम्पसन

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

1
मुझे फोर्क बम सिखाने के लिए धन्यवाद - मैंने करीब सामान किया है, जब पुनरावृत्ति को समझने की कोशिश कर रहा
हूं

2
scientamerican.com/article/… तो आधुनिक इलेक्ट्रॉनिक्स के साथ आग अभी भी संभव है।
मूविंग डक

25

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

सीधा जवाब:

1) पढ़ना लगभग कभी भी किसी अन्य प्रक्रिया को सीधे नुकसान नहीं पहुंचाएगा, हालांकि यह अप्रत्यक्ष रूप से एक प्रक्रिया को नुकसान पहुंचा सकता है यदि आप किसी प्रोग्राम / प्रक्रिया को एन्क्रिप्ट करने, डिक्रिप्ट करने या मान्य करने के लिए उपयोग किए जाने वाले कुंजी को पढ़ने के लिए करते हैं। यदि आप पढ़ रहे डेटा के आधार पर निर्णय ले रहे हैं, तो सीमा से बाहर पढ़ना आपके कोड पर कुछ प्रतिकूल / अप्रत्याशित प्रभाव डाल सकता है

2) एक ही तरीका है कि आपका कोई मेमोरी मेमोरी द्वारा सुलभ होने वाले एक लैक्टेशन को लिखकर वास्तव में कुछ डैमेज कर सकता है, यदि वह मेमोरी एड्रेस जिसे आप लिख रहे हैं, वह वास्तव में एक हार्डवेयर रजिस्टर (एक स्थान जो वास्तव में डेटा स्टोरेज के लिए नहीं है, लेकिन कुछ टुकड़े को नियंत्रित करने के लिए है) हार्डवेयर का) रैम का स्थान नहीं। सभी तथ्यों में, आप अभी भी सामान्य रूप से किसी चीज को तब तक नुकसान नहीं पहुंचाते हैं जब तक कि आप कुछ एक बार प्रोग्राम करने योग्य स्थान नहीं लिख रहे हैं जो फिर से लिखने योग्य नहीं है (या उस प्रकृति का कुछ)।

3) आम तौर पर डिबगर के भीतर से चलने वाला कोड डीबग मोड में चलता है। डिबग मोड में चलने से आपके कोड को तेजी से रोकना (लेकिन हमेशा नहीं) बंद हो जाता है, जब आपने अभ्यास से हटकर कुछ किया हो या बिलकुल अवैध हो।

4) कभी भी मैक्रोज़ का उपयोग न करें, ऐसे डेटा स्ट्रक्चर्स का उपयोग करें, जिनमें पहले से ही सरणी इंडेक्स बाउंड चेक इन आदि हों।

अतिरिक्त मुझे यह जोड़ना चाहिए कि उपरोक्त जानकारी केवल स्मृति सुरक्षा खिड़कियों के साथ ऑपरेटिंग सिस्टम का उपयोग करने वाले सिस्टम के लिए है। यदि एक एम्बेडेड सिस्टम के लिए कोड लिखना या यहां तक ​​कि ऑपरेटिंग सिस्टम (वास्तविक समय या अन्य) का उपयोग करने वाला सिस्टम जिसमें मेमोरी प्रोटेक्शन विंडो (या वर्चुअल एड्रेस विंडो) नहीं हैं, तो किसी को मेमोरी में पढ़ने और लिखने के लिए बहुत अधिक सावधानी का अभ्यास करना चाहिए। साथ ही इन मामलों में सुरक्षा मुद्दों से बचने के लिए सेफ और सिक्योर कोडिंग प्रथाओं को हमेशा नियोजित किया जाना चाहिए।


4
सुरक्षित और सुरक्षित कोडिंग प्रथाओं को हमेशा नियोजित किया जाना चाहिए ।
निक बुगालिस

3
मेरा सुझाव है कि जब तक आप बहुत विशिष्ट अपवादों को नहीं पकड़ते हैं और उनसे कैसे वसूली करते हैं, तब तक मैं छोटी गाड़ी कोड के लिए कोशिश / कैच का उपयोग नहीं करूंगा। कैच (...) सबसे खराब चीज है जिसे आप छोटी गाड़ी कोड में जोड़ सकते हैं।
यूजीन

1
@NikBougalis - मैं पूरी तरह से सहमत हूँ, लेकिन यह अधिक महत्वपूर्ण है अगर OS ​​में मेमोरी प्रोटेक्शन / वर्चुअल एड्रेस स्पेस शामिल नहीं है, या OS :-) की कमी है
trumpetlicks

@ यूजीन - मैंने कभी इस पर ध्यान नहीं दिया कि मेरे लिए एक समस्या है, लेकिन मैं आपसे सहमत हूं, क्या मैंने इसे संपादित किया है :-)
ट्रम्पेटलिक्स

1) आप नुकसान का मतलब है क्योंकि मैं कुछ रहस्य है कि गुप्त रहना चाहिए था खुलासा होगा? 2) मुझे यकीन नहीं है कि मुझे आपका मतलब क्या है, लेकिन मुझे लगता है कि मैं केवल सरणी सीमाओं के बाहर के स्थानों तक पहुंचने की कोशिश कर रहा हूं साथ ही रैम तक पहुंच रहा हूं?
क्रिस डी

9

सुरक्षा छेद सहित बदसूरत साइड इफेक्ट के लिए नेतृत्व कर सकते हैं सीमा जाँच नहीं। बदसूरत लोगों में से एक मनमाना कोड निष्पादन है । शास्त्रीय उदाहरण में: यदि आपके पास एक निश्चित आकार का सरणी है, और strcpy()उपयोगकर्ता-आपूर्ति की गई स्ट्रिंग को वहां लगाने के लिए उपयोग करते हैं, तो उपयोगकर्ता आपको एक स्ट्रिंग दे सकता है जो बफर को ओवरफ्लो करता है और कोड मेमोरी सहित अन्य मेमोरी स्थानों को अधिलेखित करता है, जहां सीपीयू को आपका फ़ंक्शन होने पर वापस आना चाहिए। खत्म।

जिसका अर्थ है कि आपका उपयोगकर्ता आपको एक स्ट्रिंग भेज सकता है जो आपके कार्यक्रम को अनिवार्य रूप से कॉल करने का कारण बनेगा exec("/bin/sh"), जो इसे शेल में बदल देगा, आपके सिस्टम पर किसी भी चीज को निष्पादित करने सहित, आपके सभी डेटा को कटाई और अपनी मशीन को बोटनेट नोड में बदल देगा।

यह कैसे किया जा सकता है, इस पर विवरण के लिए स्टैक फॉर फन एंड प्रॉफिट स्मैकिंग देखें ।


मुझे पता है कि मुझे सीमा से परे सरणी तत्वों तक नहीं पहुंचना चाहिए, उस बिंदु को मजबूत करने के लिए धन्यवाद। लेकिन सवाल यह है कि मेरे कार्यक्रम को हर तरह का नुकसान पहुंचाने के अलावा, क्या मैं अनजाने में अपने कार्यक्रम की स्मृति से परे पहुंच सकता हूं? और मेरा मतलब OSX पर है।
क्रिसड

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

मैं रिंग 0 विशेषाधिकारों के तहत कहूंगा, रूट नहीं।
रुस्लान

अधिक दिलचस्प है कि अति आधुनिक compilers फैसला कर सकते हैं कि अगर कोड की कोशिश करता पढ़ने के लिए है foo[0]के माध्यम से foo[len-1]पहले से का चेक का उपयोग कर लेने के बाद lenया तो निष्पादित या कोड का एक टुकड़ा छोड़ सरणी लंबाई के खिलाफ, संकलक बिना शर्त भी है कि अन्य कोड को चलाने के लिए स्वतंत्र महसूस करना चाहिए यदि एप्लिकेशन सरणी के पिछले भाग का संग्रहण करता है और इसे पढ़ने का प्रभाव सौम्य होगा, लेकिन अन्य कोड को लागू करने का प्रभाव नहीं होगा।
सुपर

8

तुम लिखो:

मैंने बहुत कुछ पढ़ा 'कुछ भी हो सकता है', 'विभाजन कम से कम बुरी समस्या हो सकती है', 'आपका हार्डडिस्क गुलाबी हो सकता है और यूनिकॉर्न आपकी खिड़की के नीचे गा रहा हो सकता है', जो सब अच्छा है, लेकिन वास्तव में खतरा क्या है?

चलो इसे इस तरह से रखें: एक बंदूक लोड करें। इसे खिड़की के बाहर किसी विशेष उद्देश्य और आग के बिना इंगित करें। खतरा क्या है?

मुद्दा यह है कि आप नहीं जानते हैं। यदि आपका कोड ऐसा कुछ अधिलेखित करता है जो आपके प्रोग्राम को क्रैश कर देता है तो आप ठीक हैं क्योंकि यह इसे एक परिभाषित स्थिति में रोक देगा। हालाँकि यदि यह दुर्घटनाग्रस्त नहीं होता है तो मुद्दे उत्पन्न होने लगते हैं। कौन से संसाधन आपके कार्यक्रम के नियंत्रण में हैं और यह उनके लिए क्या कर सकता है? कौन से संसाधन आपके कार्यक्रम के नियंत्रण में हो सकते हैं और यह उनके लिए क्या कर सकता है? मुझे पता है कि कम से कम एक प्रमुख मुद्दा जो इस तरह के अतिप्रवाह के कारण था। मुद्दा एक प्रतीत होता है कि अर्थहीन आँकड़े फ़ंक्शन में था, जिसने उत्पादन डेटाबेस के लिए कुछ असंबंधित रूपांतरण तालिका को गड़बड़ कर दिया था। परिणाम बाद में कुछ बहुत महंगा सफाई था। वास्तव में यह बहुत सस्ता और आसान होता अगर इस मुद्दे को हार्ड डिस्क को प्रारूपित किया जाता ... अन्य शब्दों के साथ: गुलाबी गेंडा आपकी कम से कम समस्या हो सकती है।

यह विचार कि आपका ऑपरेटिंग सिस्टम आपकी रक्षा करेगा, आशावादी है। यदि संभव हो तो सीमा से बाहर लिखने से बचने की कोशिश करें।


ठीक है, यह वही था जिससे मैं डरता था। मैं 'सीमा से बाहर लिखने से बचने की कोशिश करूँगा' लेकिन, पिछले कुछ महीनों से जो कुछ भी मैं कर रहा हूँ, उसे देखते हुए, मैं निश्चित रूप से अभी भी बहुत कुछ कर रहा हूँ। अभ्यास के सुरक्षित तरीके के बिना आप लोगों को प्रोग्रामिंग में इतना अच्छा कैसे मिला?
क्रिस डी

3
किसने कहा कि कुछ भी कभी सुरक्षित था;)
उडो क्लेन

7

अपने प्रोग्राम को रूट या किसी अन्य विशेषाधिकार प्राप्त उपयोगकर्ता के रूप में नहीं चलाने से आपके सिस्टम को कोई नुकसान नहीं होगा, इसलिए आमतौर पर यह एक अच्छा विचार हो सकता है।

कुछ रैंडम मेमोरी लोकेशन पर डेटा लिखने से आप अपने कंप्यूटर पर चल रहे किसी अन्य प्रोग्राम को सीधे "नुकसान" नहीं करेंगे क्योंकि प्रत्येक प्रक्रिया स्वयं मेमोरी स्पेस में चलती है।

यदि आप अपनी प्रक्रिया को आवंटित नहीं की गई किसी भी मेमोरी को एक्सेस करने का प्रयास करते हैं, तो ऑपरेटिंग सिस्टम आपके प्रोग्राम को विभाजन दोष के साथ निष्पादित करने से रोक देगा।

तो सीधे (रूट के रूप में चलने के बिना और सीधे / देव / मेम जैसी फ़ाइलों को एक्सेस करने के बिना) कोई खतरा नहीं है कि आपका प्रोग्राम आपके ऑपरेटिंग सिस्टम पर चलने वाले किसी अन्य प्रोग्राम के साथ हस्तक्षेप करेगा।

फिर भी - और शायद यह वही है जो आपने खतरे के बारे में सुना है - गलती से यादृच्छिक डेटा को यादृच्छिक मेमोरी स्थानों पर लिखने से आप सुनिश्चित कर सकते हैं कि आप जो कुछ भी नुकसान पहुंचा सकते हैं, उसे नुकसान पहुंचा सकते हैं।

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


1
यदि आप रूट (या कुछ अन्य विशेषाधिकार प्राप्त उपयोगकर्ता) के रूप में चल रहे हैं , तो बाहर देखें। बफर और एरे ओवररन एक सामान्य मालवेयर शोषण हैं।
जॉन बोडे

वास्तव में मैं अपने सभी दैनिक कंप्यूटिंग के लिए जिस खाते का उपयोग करता हूं वह व्यवस्थापक खाता नहीं है (मैं OSX शब्दावली का उपयोग करता हूं क्योंकि यह मेरी प्रणाली है)। क्या आपको यह बताने का मतलब है कि मैं किसी भी मेमोरी स्थान को सेट करने की कोशिश करके संभवतः कुछ नुकसान नहीं पहुंचा सकता हूं? यह वास्तव में बहुत अच्छी खबर है!
क्रिस डी

जैसा कि पहले ही उल्लेख किया जा चुका है कि दुर्घटना से सबसे अधिक नुकसान आप एक उपयोगकर्ता के रूप में कर सकते हैं। यदि आप 100% सुनिश्चित होना चाहते हैं कि आप अपने किसी भी डेटा को नष्ट न करें तो शायद आप अपने कंप्यूटर में अलग खाता जोड़ना चाहें और उसी के साथ प्रयोग कर सकें।
मिकायरा

1
@ मायिक्रा: यह तभी सच है जब सिस्टम के सुरक्षात्मक तंत्र 100% प्रभावी हों। मैलवेयर का अस्तित्व बताता है कि आप हमेशा उस पर भरोसा नहीं कर सकते। (मैं यह सुझाव नहीं देना चाहता कि इसके बारे में चिंता करने लायक है; यह संभव है, लेकिन संभावना नहीं है, कि कोई प्रोग्राम गलती से मैलवेयर द्वारा शोषण किए गए समान सुरक्षा छेद का शोषण कर सकता है।)
कीथ थॉम्पसन

1
यहाँ सूची में शामिल हैं: अविश्वासित स्रोतों से कोड चलाना। फायरवॉल के किसी भी पॉपअप पर ओके बटन पर क्लिक किए बिना यह पढ़े कि यह किस बारे में है या वांछित नेटवर्क कनेक्शन नहीं बनाया जा सकता है तो इसे पूरी तरह से बंद कर दें। संदिग्ध स्रोतों से नवीनतम हैक के साथ बायनेरिज़ पैचिंग। यह तिजोरी का दोष नहीं है अगर मालिक स्वेच्छा से किसी भी बर्गलर को दोनों हाथों से और अतिरिक्त मजबूत किलेबंद दरवाजे को खुले में आमंत्रित करेगा।
मायिकरा

4

NSArrayऑब्जेक्टिव-सी में मेमोरी का एक विशिष्ट ब्लॉक दिया जाता है। सरणी की सीमा से अधिक होने का मतलब है कि आप उस मेमोरी तक पहुंच पाएंगे जो सरणी को असाइन नहीं की गई है। इसका मतलब है की:

  1. इस मेमोरी का कोई मूल्य हो सकता है। यह जानने का कोई तरीका नहीं है कि डेटा आपके डेटा प्रकार के आधार पर मान्य है या नहीं।
  2. इस मेमोरी में संवेदनशील जानकारी हो सकती है जैसे निजी कुंजी या अन्य उपयोगकर्ता क्रेडेंशियल।
  3. स्मृति पता अमान्य या संरक्षित हो सकता है।
  4. मेमोरी में एक बदलते मूल्य हो सकते हैं क्योंकि इसे किसी अन्य प्रोग्राम या थ्रेड द्वारा एक्सेस किया जा रहा है।
  5. अन्य चीजें मेमोरी एड्रेस स्पेस का उपयोग करती हैं, जैसे मेमोरी-मैप्ड पोर्ट्स।
  6. अज्ञात मेमोरी पते पर डेटा लिखना आपके प्रोग्राम को क्रैश कर सकता है, ओएस मेमोरी स्पेस को अधिलेखित कर सकता है, और आमतौर पर सूरज को फंसाने का कारण बन सकता है।

अपने कार्यक्रम के पहलू से आप हमेशा यह जानना चाहते हैं कि आपका कोड किसी सरणी की सीमा से अधिक है या नहीं। इससे अज्ञात मान लौटाए जा सकते हैं, जिससे आपका एप्लिकेशन क्रैश हो सकता है या अमान्य डेटा प्रदान कर सकता है।


NSArraysसीमा से बाहर है। और यह प्रश्न C सरणी के बारे में है।
ड्रमर बी

मैं वास्तव में सी सरणियों का मतलब है। मुझे पता है कि NSArray है, लेकिन अभी मेरे ज्यादातर अभ्यास C
ChrisD

4

आप Valgrindmemcheck में टूल का उपयोग करने का प्रयास कर सकते हैंजब आप अपने कोड का परीक्षण करते हैं, तो आप - यह एक स्टैक फ्रेम के भीतर व्यक्तिगत सरणी सीमा उल्लंघन नहीं पकड़ेगा, लेकिन यह कई अन्य प्रकार की मेमोरी समस्या को पकड़ सकता है, जिनमें सूक्ष्म, व्यापक कारण होंगे। किसी एकल फ़ंक्शन के दायरे से बाहर की समस्याएं।

मैनुअल से:

मेमचेक एक मेमोरी एरर डिटेक्टर है। यह निम्न समस्याओं का पता लगा सकता है जो C और C ++ प्रोग्राम में सामान्य हैं।

  • मेमोरी को एक्सेस नहीं करना चाहिए, जैसे कि ओवररिंग और अंडरराइटिंग हीप ब्लॉक, स्टैक के शीर्ष को ओवररेंज करना, और फ्री होने के बाद मेमोरी एक्सेस करना।
  • अपरिभाषित मानों का उपयोग करना, अर्थात ऐसे मान जिनका प्रारंभ नहीं किया गया है, या जिन्हें अन्य अपरिभाषित मानों से लिया गया है।
  • हीप मेमोरी को गलत तरीके से मुक्त करना, जैसे डबल-फ्रीप हीप ब्लॉक्स, या मल्चॉक का बेमेल उपयोग / नया / नया [] बनाम फ्री / डिलीट / डिलीट []
  • Memcpy और संबंधित कार्यों में src और dst पॉइंटर्स को ओवरलैप करना।
  • स्म्रति से रिसाव।

ETA: हालाँकि, जैसा कि कज़ का जवाब कहता है, यह एक रामबाण नहीं है, और हमेशा सबसे उपयोगी आउटपुट नहीं देता है, खासकर जब आप रोमांचक एक्सेस पैटर्न का उपयोग कर रहे हैं ।


मुझे शक है कि एक्सकोड के एनालाइज़र को इसका सबसे ज्यादा पता चलेगा? और मेरा सवाल इतना नहीं है कि इन बगों को कैसे खोजा जाए, लेकिन अगर किसी प्रोग्राम को निष्पादित करना है जो अभी भी इन बगों में है, तो मेरे कार्यक्रम के लिए आवंटित नहीं किया गया स्मृति के लिए खतरनाक है। मुझे बग्स को देखने के लिए कार्यक्रम को निष्पादित करना होगा
क्रिस

3

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

एक उदाहरण फ्लैश मेमोरी की प्रोग्रामिंग है। मेमोरी चिप्स पर प्रोग्रामिंग मोड चिप के एड्रेस रेंज के अंदर विशिष्ट स्थानों पर मूल्यों का एक विशिष्ट अनुक्रम लिखकर सक्षम किया गया है। यदि कोई अन्य प्रक्रिया चिप में किसी अन्य स्थान पर लिखी जाती है, जबकि यह चल रहा था, तो यह प्रोग्रामिंग चक्र को विफल कर देगा।

कुछ मामलों में हार्डवेयर चारों ओर के पते लपेटेंगे (पते के सबसे महत्वपूर्ण बिट्स / बाइट्स को नजरअंदाज कर दिया जाता है) इसलिए भौतिक पते के स्थान के अंत से परे एक पते पर लिखना वास्तव में डेटा को चीजों के बीच में सही लिखा जाएगा।

और अंत में, MC68000 जैसे पुराने CPU इस बिंदु पर लॉक हो सकते हैं कि केवल एक हार्डवेयर रीसेट उन्हें फिर से जा सकता है। कुछ दशकों तक उन पर काम नहीं किया गया था, लेकिन मेरा मानना ​​है कि जब एक अपवाद को संभालने की कोशिश करते समय यह बस त्रुटि (गैर-मौजूद स्मृति) का सामना करता था, तो यह बस तब तक रुकता था जब तक कि हार्डवेयर रीसेट मुखर नहीं हो जाता।

मेरी सबसे बड़ी सिफारिश एक उत्पाद के लिए एक स्पष्ट प्लग है, लेकिन मुझे इसमें कोई व्यक्तिगत रुचि नहीं है और मैं किसी भी तरह से उनके साथ संबद्ध नहीं हूं - लेकिन सी प्रोग्रामिंग और एम्बेडेड सिस्टम के कुछ दशकों के आधार पर जहां विश्वसनीयता महत्वपूर्ण थी, जिम्पेल का पीसी लिंट न केवल उन त्रुटियों का पता लगाएगा, यह आपके द्वारा लगातार बेहतर C / C ++ प्रोग्रामर को बाहर कर देगा बुरी आदतों के बारे में नुकसान पहुंचाकर ।

मैं भी MISRA C कोडिंग मानक को पढ़ने की सलाह दूंगा, यदि आप किसी से एक प्रति ले सकते हैं। मैंने हाल ही में किसी को नहीं देखा है, लेकिन तु पुराने दिनों में उन्होंने इस बात की अच्छी व्याख्या की थी कि आपको उन चीजों को क्यों नहीं करना चाहिए / जिन्हें वे कवर नहीं करते।

आपके बारे में पता नहीं है, लेकिन दूसरी या दूसरी बार मुझे किसी भी एप्लिकेशन से एक coredump या hangup मिलता है, जो भी कंपनी ने इसे उत्पादित किया है उसकी मेरी राय आधे से नीचे चली जाती है। 4 या 5 वीं बार और जो कुछ भी पैकेज शेल्फवेयर बन जाता है और मैं पैकेज के केंद्र के माध्यम से एक लकड़ी की हिस्सेदारी चलाता हूं / डिस्क में बस यह सुनिश्चित करने के लिए आया था कि यह मुझे वापस करने के लिए कभी नहीं आता है।


सिस्टम के आधार पर, आउट-ऑफ-रेंज रीड्स अप्रत्याशित व्यवहार को भी ट्रिगर कर सकते हैं, या वे सौम्य हो सकते हैं, हालांकि आउट-ऑफ-रेंज लोड पर सौम्य हार्डवेयर व्यवहार सौम्य संकलक व्यवहार को प्रभावित नहीं करता है।
सुपर

2

मैं एक डीएसपी चिप के लिए एक कंपाइलर के साथ काम कर रहा हूं जो जानबूझकर कोड उत्पन्न करता है जो सी कोड से एक सरणी के अंत में एक अतीत तक पहुंचता है जो नहीं करता है!

ऐसा इसलिए है क्योंकि छोरों को संरचित किया जाता है ताकि एक पुनरावृत्ति का अंत अगले पुनरावृत्ति के लिए कुछ डेटा को प्रीफ़ेट करता है। इसलिए अंतिम पुनरावृत्ति के अंत में पूर्व निर्धारित डेटा का उपयोग वास्तव में कभी नहीं किया जाता है।

उस तरह का C कोड लिखना जो अपरिभाषित व्यवहार को आमंत्रित करता है, लेकिन यह केवल एक मानक दस्तावेज़ से एक औपचारिकता है जो अधिकतम पोर्टेबिलिटी के साथ खुद को चिंतित करता है।

अधिक बार ऐसा नहीं है, एक कार्यक्रम जो सीमा से बाहर पहुंचता है, चतुराई से अनुकूलित नहीं है। यह बस छोटी गाड़ी है। कोड कुछ कचरा मूल्य प्राप्त करता है और, उपरोक्त कंपाइलर के अनुकूलित लूप के विपरीत, कोड इसके बाद के कम्प्यूटेशंस में मूल्य का उपयोग करता है, जिससे उन्हें समाप्‍त किया जाता है।

यह उस तरह के कीड़े को पकड़ने के लायक है, और इसलिए यह व्यवहार को केवल उस कारण के लिए भी अपरिभाषित बनाने के लायक है: ताकि रन-टाइम एक नैदानिक ​​संदेश का उत्पादन कर सके जैसे "सरणी के मेन 42 में लाइन ओवररन"।

वर्चुअल मेमोरी वाले सिस्टम पर, एक ऐरे को आबंटित किया जा सकता है जैसे कि वह पता जो निम्न प्रकार से वर्चुअल मेमोरी के अनमैप्ड एरिया में हो। फिर पहुंच कार्यक्रम को बम बनाएगी।

एक तरफ के रूप में, ध्यान दें कि सी में हमें एक पॉइंटर बनाने की अनुमति है जो एक सरणी के अंत में एक है। और इस पॉइंटर को किसी भी पॉइंटर से अधिक की तुलना किसी ऐरे के इंटीरियर से करनी होती है। इसका अर्थ है कि C कार्यान्वयन स्मृति के अंत में एक सरणी को सही स्थान पर नहीं रख सकता है, जहां एक प्लस पता चारों ओर लपेटेगा और सरणी में अन्य पते से छोटा दिखेगा।

फिर भी, असमान या बिना सीमा के मूल्यों तक पहुंच कभी-कभी अधिकतम पोर्टेबल न होने पर भी एक वैध अनुकूलन तकनीक है। यह उदाहरण के लिए है कि क्यों Valgrind उपकरण अनइंस्टॉल किए गए डेटा तक पहुंच की रिपोर्ट नहीं करता है जब वे एक्सेस होते हैं, लेकिन केवल तब जब मूल्य बाद में किसी तरह से उपयोग किया जाता है जो प्रोग्राम के परिणाम को प्रभावित कर सकता है। आपको "एक्सटर्नल ब्रांच इन एक्सएक्सएक्स: एनएनएन अनइंस्टाल्यूटेड वैल्यू पर निर्भर करता है" जैसा एक डायग्नोस्टिक मिलता है और यह कभी-कभी नीचे ट्रैक करने के लिए कठिन हो सकता है जहां यह उत्पन्न होता है। यदि इस तरह की सभी पहुंच तुरंत फंसी हुई थी, तो कंपाइलर ऑप्टिमाइज्ड कोड के साथ-साथ सही तरीके से हाथ से ऑप्टिमाइज़ किए गए कोड से उत्पन्न होने वाली कई झूठी सकारात्मकताएं भी होंगी।

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

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


इसके अतिरिक्त, बशर्ते कि कम से कम एक कार्यक्रम मौजूद हो, जो किसी विशेष कार्यान्वयन प्रक्रिया को सही ढंग से पूरा करता हो, भले ही यह मानक में दी गई सभी कार्यान्वयन सीमाओं पर कर लगाता हो, यह कार्यान्वयन किसी अन्य कार्यक्रम को खिलाए जाने पर मनमाने ढंग से व्यवहार कर सकता है, जो बाधाओं से मुक्त है और अभी भी " शिकायत "। नतीजतन, सी कार्यक्रमों के 99.999% (एक मंच के "एक कार्यक्रम" के अलावा कुछ भी) उन व्यवहारों पर भरोसा करते हैं जहां मानक अपनी आवश्यकताओं को लागू करता है।
सुपरकैट

1

अपने स्वयं के कार्यक्रम के अलावा, मुझे नहीं लगता कि आप कुछ भी तोड़ देंगे, सबसे खराब स्थिति में आप एक स्मृति पते से पढ़ने या लिखने की कोशिश करेंगे जो उस पृष्ठ से मेल खाती है जो कर्नेल ने आपके प्रॉसेस को असाइन नहीं किया था, उचित अपवाद उत्पन्न करता है और मारा जा रहा है (मेरा मतलब है, आपकी प्रक्रिया)।


3
..क्या? अपनी स्वयं की प्रक्रिया में ओवरराइटिंग मेमोरी के बारे में कैसे बाद में उपयोग किए जाने वाले कुछ चर को संग्रहीत करने के लिए उपयोग किया जाता है ... जो अब रहस्यमय तरीके से इसके मूल्य को बदल दिया है! उन बगों को नीचे ट्रैक करने के लिए मज़े का भार है, मैं आपको आश्वासन देता हूं। एक segfault सबसे अच्छा परिणाम होगा। -1
एड एस।

2
मेरा मतलब है कि वह अपने स्वयं के कार्यक्रम के अलावा अन्य प्रक्रियाओं को "नहीं" तोड़ देगा;
21

मैं वास्तव में परवाह नहीं करता हूं अगर मैं अपना खुद का कार्यक्रम तोड़ता हूं। मैं सिर्फ सीख रहा हूं, कार्यक्रम स्पष्ट रूप से वैसे भी गलत है अगर मैं अपने सरणी से बंधे कुछ भी उपयोग करता हूं। मैं अपनी रचनाओं को डीबग करते समय कुछ और तोड़ने के जोखिमों के बारे में अधिक से अधिक चिंतित हूं
क्रिसड

बात यह है: क्या मैं निश्चित हो सकता हूं यदि मैं स्मृति को एक्सेस करने का प्रयास करता हूं जो मुझे सौंपा नहीं गया है, कि मेरी प्रक्रिया को मार दिया जाएगा? (OSX पर होने के नाते)
क्रिस डी

3
वर्षों पहले, मैं एक अनाड़ी सी प्रोग्रामर हुआ करता था। मैंने सैकड़ों बार उनकी सीमा के बाहर सरणियों का उपयोग किया। ऑपरेटिंग सिस्टम द्वारा मारे जाने की मेरी प्रक्रिया के अलावा, कभी कुछ नहीं हुआ।
jbgs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.