2015-03-17 2 views
8

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

उदाहरण के लिए, मान लीजिए कि मेरे पास एक ऐसा फ़ंक्शन है जो सफलता पर 0 या वापस देता है - अगर इसे एक पूर्ण तर्क दिया जाता है। क्या मैं स्वाभाविक रूप से करना है:

int err; 
struct myctx ctx; 
err = callFunction(&ctx); 
if (err != 0) 
{ 
    abort(); 
} 

या यहाँ तक कि:

int err; 
struct myctx ctx; 
err = callFunction(&ctx); 
if (err == -EINVAL) 
{ 
    abort(); 
} 
else if (err != 0) 
{ 
    abort(); 
} 

... -EINVAL के दो मामलों और अज्ञात त्रुटि कोड के बीच अंतर करना।

इस त्रुटि प्रबंधन दृष्टिकोण के लाभ यह है कि यह प्रोग्राम (कोड की कुछ पंक्तियां) के लिए आसान है और कोर फ़ाइल के पीछे छोड़ देता है जिसका उपयोग स्थिति को जल्दी से डीबग करने के लिए किया जा सकता है।

हालांकि, कुछ टीम सदस्य इस त्रुटि प्रबंधन दृष्टिकोण से असहमत हैं क्योंकि मैं एक अशुद्ध निकास कर रहा हूं और वर्तमान में कोड कभी भी निरस्त() लाइन तक नहीं पहुंच सकता है, भविष्य में कोई भी कोड को संशोधित करता है और यह पहुंचता है तब abort() लाइन। उनके अनुसार, मुझे नियंत्रित निकास करने और उपयोगकर्ता को कारण मुद्रित करने का प्रयास करना चाहिए। तो, मैं इस के बजाय लगता है कि मुझे क्या करना चाहिए:

int err; 
struct myctx ctx; 
err = callFunction(&ctx); 
if (err == -EINVAL) 
{ 
    fprintf(stderr, "Argument was NULL in file %s line %d\n", __FILE__, __LINE__); 
    exit(1); 
} 
else if (err != 0) 
{ 
    fprintf(stderr, "Error was %d in file %s line %d\n", err, __FILE__, __LINE__); 
    exit(1); 
} 

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

तो सवाल यह है कि सी में त्रुटियों की शैली को "कभी नहीं किया जा सकता" शैली को कैसे संभाला जाना चाहिए? क्या मुझे एक वर्णनात्मक त्रुटि संदेश के साथ निरस्त या नियंत्रित निकास करना चाहिए?

+1

जबकि मुझे सवाल पसंद है, यह काफी राय आधारित है। – martin

+1

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

+0

धन्यवाद! मुझे लगता है कि कि एक कोर डंप पैदा करने से एक में चल रहे एप्लिकेशन मौजूद है की अनुमति देता है एक coredumper पुस्तकालय। मैं gcore के बारे में पता था, हालांकि पता नहीं था, लेकिन यह एक अलग आदेश है और नहीं एक पुस्तकालय है कि आवेदन मैं programmers.stackexch की जानकारी नहीं थी – juhist

उत्तर

4

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

हालाँकि, व्यवहार में, अपने अस्पष्टीकृत abort() पहले उदाहरण में सबसे हर कोई है, क्योंकि यह तेजी से लिखने के लिए क्या करता है है। इसका नतीजा यह है कि अधिकांश अनुप्रयोग, जब वे असफल होते हैं, तो बुरी तरह से बाहर निकलें। उदाहरण के लिए, जब माइक्रोसॉफ्ट वर्ड दुर्घटनाग्रस्त हो जाता है, तो उपयोगकर्ता को संदेश "शब्द में एक समस्या आई है और अब बाहर निकल जाएगी।" या प्रभाव के लिए कुछ है। कई एप्लिकेशन बिल्कुल कोई संदेश नहीं देते हैं लेकिन बस समाप्त होते हैं।

उचित प्रोग्रामिंग पूरी तरह से कोड करने के लिए है जिसे नकारात्मक पथ कहा जाता है। न केवल प्रत्येक संभावित विफलता को एक सार्थक पाठ संदेश उत्पन्न करना चाहिए, लेकिन विफलता के रूप में कॉल श्रृंखला के माध्यम से विफलता वापस आती है और प्रत्येक कॉलिंग फ़ंक्शन को इसके संदर्भ और संदेश के सामने किसी प्रासंगिक पैरामीटर को जोड़ना चाहिए। \ उपयोगकर्ता \ डेटा \ विन्यास: [ग पर विन्यास फ़ाइल को लोड करते समय: प्रारंभ करने का प्रयास करते समय

: तो उपयोगकर्ता के लिए अंत संदेश कुछ इस तरह होना चाहिए।आरं]: अमान्य पैरामीटर मान 'NumRedirects' (सीमा से बाहर): -43

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

2

मुझे लगता है कि यह दावा क्या है। वापसी मान तब तक चेक किया जाता है जब तक कोड NDEBUG परिभाषित नहीं किया जाता है।

#include <assert.h> 
... 
int err; 
struct myctx ctx; 
err = callFunction(&ctx); 
assert(err != -EINVAL); 
assert(err == 0); 

विचार है कि कीड़े आमतौर पर अप्रत्याशित को जन्म दे रहा है। साथ ही, कथन कोड के पठनीयता को बढ़ाएं। जब दावा विफल रहता है स्वचालित त्रुटि संदेश प्रोग्रामर को असफल दावा की पहचान करने में मदद करता है। शाखाओं की संख्या को कम करने के लिए रिलीज संस्करण -DNDEBUG के साथ बनाया जा सकता है।

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