आपके C ++ कोड में अपवाद सुरक्षा कितनी महत्वपूर्ण है?


19

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

Level::Entity* entity = new Level::Entity();
entity->id = GetNextId();
entity->AddComponent(new Component::Position(x, y));
entity->AddComponent(new Component::Movement());
entity->AddComponent(new Component::Render());
allEntities.push_back(entity); // std::vector
entityById[entity->id] = entity; // std::map
return entity;

एक मूल अपवाद गारंटी को लागू करने के लिए, मैं newकॉल पर एक स्कॉप्ड पॉइंटर का उपयोग कर सकता हूं । यदि कोई कॉल अपवाद को फेंकने के लिए स्मृति लीक को रोकती है।

हालाँकि, मान लें कि मैं एक मजबूत अपवाद गारंटी लागू करना चाहता हूं। कम से कम, मैं अपने कंटेनर के लिए एक साझा सूचक (मैं बूस्ट का उपयोग नहीं), एक nothrow लागू करने के लिए की आवश्यकता होगी Entity::Swapatomically घटकों को जोड़ने के लिए, और atomically दोनों को जोड़ने के लिए मुहावरा किसी प्रकार का Vectorऔर Map। न केवल इन्हें लागू करने में समय लगेगा, बल्कि वे महंगे होंगे क्योंकि इसमें अपवाद असुरक्षित समाधान की तुलना में बहुत अधिक नकल शामिल है।

अंतत: मुझे ऐसा लगता है कि उस समय को व्यतीत करते हुए वह सब कुछ उचित नहीं होगा, ताकि एक साधारण CreateEntityकार्य दृढ़ता से अपवाद के रूप में सुरक्षित रहे। मैं शायद सिर्फ खेल को एक त्रुटि प्रदर्शित करना चाहता हूं और उस बिंदु पर बंद करना चाहता हूं।

आप इसे अपने गेम प्रोजेक्ट्स में कितनी दूर लेते हैं? क्या यह आम तौर पर एक प्रोग्राम के लिए अपवाद असुरक्षित कोड लिखने के लिए स्वीकार्य है जो अपवाद होने पर बस दुर्घटनाग्रस्त हो सकता है?


21
जब मैंने पूर्व में C ++ प्रोजेक्ट्स पर काम किया था, तो मूल रूप से हमने जो अपवाद का दावा किया था, वह मौजूद नहीं था।
तेतराड

2
मैं, व्यक्तिगत रूप से, अपवादों को प्यार करता हूं और अक्सर वास्तव में यह पता लगाने का आनंद लेता हूं कि कैसे अपने कोड को मजबूत गारंटी प्रदान करें। यदि आप अपवाद होने पर बस दुर्घटनाग्रस्त होने जा रहे हैं ... तो शायद इससे परेशान न हों।

7
मैं व्यक्तिगत रूप से .. hm .. 'अपवादों को प्रबंधित करने के लिए अपवादों का उपयोग करता हूं, त्रुटियों का नहीं। जैसे, अगर मुझे पता है कि कोई फंक्शन क्रैश हो सकता है, तो मैं इसे क्रैश कर देता हूं, लेकिन अगर मुझे पता है कि फंक्शन शायद एक आर्काइव को सफलतापूर्वक नहीं पढ़ सकता है, लेकिन एक और तरीका है, तो मैं इसे एक कोशिश के साथ घेरता हूं, पकड़ता हूं। और अगर इसका "पढ़ने में असमर्थ" अपवाद है, तो मैं इसे दूसरे तरीके से प्रबंधित करता हूं जैसे कि मैं संग्रह पढ़ने के बिना करूंगा।
गुस्तावो मैकिएल

Gtoknu ने क्या कहा, आपको इस बात से अवगत होने की आवश्यकता है कि कोई भी बाहरी लाइब्रेरियन कौन से अपवादों को फेंक सकता है।
पीटर Peterलस्टेड

जवाबों:


26

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

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

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

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


12
यह अकेले एक +1 के लायक है: "कोड जो अपवादों का उपयोग नहीं करता है और स्पष्ट रूप से अपवाद सुरक्षित नहीं है, कोड की तुलना में बेहतर है जो उनका उपयोग करता है, लेकिन इसकी अपवाद सुरक्षा का आधा समर्थन करता है।"
मैक्सिमस मिनिमस

14

अंगूठे का मेरा सामान्य नियम: यदि आपको अपवादों का उपयोग करने की आवश्यकता है, तो अपवादों का उपयोग करें। यदि आपको अपवादों का उपयोग करने की आवश्यकता नहीं है, तो अपवादों का उपयोग न करें। यदि आप यह नहीं जानते कि आपको अपवादों का उपयोग करने की आवश्यकता है या नहीं, तो आपको अपवादों का उपयोग करने की आवश्यकता नहीं है।

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

दूसरी ओर, गेम को विकसित करते समय, आप मंत्र का अनुसरण करते हुए बहुत बेहतर होते हैं: क्रैश जल्दी, क्रैश ज़ोर से। यदि कोई समस्या है, तो आप वास्तव में जल्द से जल्द इसके बारे में जानना चाहते हैं; आप कभी भी त्रुटियों को अदृश्य रूप से 'नियंत्रित' नहीं करना चाहते हैं, क्योंकि यह अक्सर बाद के दुर्व्यवहारों के वास्तविक कारण को छिपाएगा और डीबगिंग को जितना संभव हो उतना मुश्किल बना देगा।


5

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

खेल के विकास के लिए मैं कोशिश करना पसंद करता हूं और संभव होने पर विफलताओं के साथ अपने कोड को विनम्रतापूर्वक जारी रखने के तरीके ढूंढता हूं।

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

घटना में एक सामान्य लोडमेश कॉल कुछ त्रुटि को वापस फेंकने और डेस्कटॉप को क्रैश करने के बजाय विफल हो जाता है, यह चुपचाप विफलता को कंसोल / लॉगफाइल में प्रवेश करेगा और हार्डकोड त्रुटि जाल को वापस करेगा। मुझे पता चला कि Skyrim वास्तव में वही काम करता है जब एक मॉड खराब हो जाता है। इस बात की अच्छी संभावना है कि खिलाड़ी भी त्रुटि जाल को नहीं देखेगा (जब तक कि कोई बड़ी समस्या नहीं है और उनमें से कई इसे पसंद करते हैं)।

एक फॉलबैक शेडर भी है। एक जो कि बुनियादी वर्टेक्स मैट्रिक्स ऑपरेशन करता है, लेकिन अगर किसी कारण से कोई समान मैट्रिक्स नहीं है, तो भी इसे ऑर्थोगोनल व्यू करना चाहिए। इसकी कोई उचित छायांकन / प्रकाश / सामग्री नहीं है (हालाँकि इसमें एक color_overide ध्वज है ताकि मैं इसे अपनी त्रुटि जाल के साथ उपयोग कर सकूँ)।

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

'नए' के ​​मामले में, खेल के विकास के लिए किसी तरह के कारखाने का उपयोग करना बेहतर हो सकता है। इससे पहले कि आप वास्तव में उन्हें जरूरत है और / या थोक में उन्हें बनाने से पहले वस्तुओं का प्रचार करने जैसे कई अन्य लाभ दे सकते हैं। यह वस्तुओं के वैश्विक सूचकांक जैसी चीजों को बनाना भी आसान बनाता है जिनका उपयोग आप मेमोरी मैनेजमेंट के लिए कर सकते हैं, एक आईडी द्वारा चीजों को ढूंढना, (हालांकि आप ऐसा कंस्ट्रक्टरों में भी कर सकते हैं)। और निश्चित रूप से आप वहाँ भी आवंटन त्रुटियों को संभाल सकते हैं।


2

लापता रनटाइम चेक और क्रैश के बारे में बड़ी बात एक हैकर के लिए प्रक्रिया को संभालने के लिए क्रैश का उपयोग करने की क्षमता है और शायद बाद में मशीन।

अब, एक हैकर वास्तविक दुर्घटना का शोषण नहीं कर सकता, जैसे ही दुर्घटना होती है प्रक्रिया बेकार और हानिरहित है। यदि आप बस एक नल सूचक से पढ़ते हैं तो यह एक साफ दुर्घटना है, आप एक गलती करते हैं और प्रक्रिया तुरंत मर जाती है।

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

एक अनकहा अपवाद वास्तव में एक वास्तविक दुर्घटना नहीं है, यह कार्यक्रम को समाप्त करने का एक तरीका है। अपवाद केवल इसलिए होते हैं क्योंकि किसी ने एक पुस्तकालय लिखा था जो विशेष रूप से कुछ परिस्थितियों को देखते हुए एक अपवाद फेंकता है। आमतौर पर एक अप्रत्याशित स्थिति में जाने से बचने के लिए, जो एक हैकर के लिए एक शुरुआत हो सकती है।

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

उन त्रुटियों पर ध्यान केंद्रित करें जो आवश्यक रूप से अपवाद नहीं फेंकते हैं, जैसे कि एक सरणी के अंत से परे लिखना। आपका कार्यक्रम संयोग से ऐसा नहीं कर पाएगा?


2

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

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


1

यकीन नहीं होता कि किसी और को उद्धृत करना एसई पर उचित है लेकिन मुझे लगता है कि वास्तव में इस पर छपे अन्य उत्तरों में से कोई भी नहीं है।

अपनी पुस्तक गेम इंजन आर्किटेक्चर से जेसन ग्रेगरी का उद्धरण । (महान बुक!)

"संरचित अपवाद हैंडलिंग (एसईएच) कार्यक्रम के लिए बहुत सारे ओवरहेड जोड़ता है। स्टैक अन्डरिंग प्रक्रिया द्वारा आवश्यक अतिरिक्त जानकारी शामिल करने के लिए प्रत्येक स्टैक फ्रेम को संवर्धित किया जाना चाहिए। इसके अलावा, दो से तीन के क्रम पर स्टैक को खोलना आमतौर पर बहुत धीमा होता है। केवल फ़ंक्शन से लौटने से कई गुना अधिक महंगा है। इसके अलावा, यदि आपके प्रोग्राम (या लाइब्रेरी) में कोई फ़ंक्शन SEH का उपयोग करता है, तो आपके पूरे प्रोग्राम को SEH का उपयोग करना होगा। कंपाइलर यह नहीं जान सकता है कि कॉल स्टैक पर आपके ऊपर कौन से फ़ंक्शन हो सकते हैं। आप एक अपवाद फेंक देते हैं। "

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


2
संरचित अपवाद हैंडलिंग विंडोज पर उपलब्ध एक विशिष्ट प्रकार का अपवाद हैंडलिंग है, जो आमतौर पर C ++ अपवादों के समान नहीं है।
Kylotan

दोहा, मुझे विश्वास नहीं हो रहा है कि मैं यह नहीं जानता था। सुधारों के लिए धन्यवाद!
क्लेशनिकोवकिड

0

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.