C में, आप स्पष्ट त्रुटि हैंडलिंग के लिए if + goto के मैन्युअल उपयोग के माध्यम से स्वचालित "ऑब्जेक्ट रिक्लेमेशन" के साथ अपवादों का "अनुकरण" कर सकते हैं।
मैं अक्सर निम्नलिखित की तरह सी कोड लिखता हूं (त्रुटि हैंडलिंग को उजागर करने के लिए उबला हुआ):
#include <assert.h>
typedef int errcode;
errcode init_or_fail( foo *f, goo *g, poo *p, loo *l )
{
errcode ret = 0;
if ( ( ret = foo_init( f ) ) )
goto FAIL;
if ( ( ret = goo_init( g ) ) )
goto FAIL_F;
if ( ( ret = poo_init( p ) ) )
goto FAIL_G;
if ( ( ret = loo_init( l ) ) )
goto FAIL_P;
assert( 0 == ret );
goto END;
/* error handling and return */
/* Note that we finalize in opposite order of initialization because we are unwinding a *STACK* of initialized objects */
FAIL_P:
poo_fini( p );
FAIL_G:
goo_fini( g );
FAIL_F:
foo_fini( f );
FAIL:
assert( 0 != ret );
END:
return ret;
}
यह पूरी तरह से मानक एएनएसआई सी है, अपने मेनलाइन कोड से दूर होने वाली त्रुटि को अलग करता है, प्रारंभिक वस्तुओं की सीडिंग करता है जैसे कि सी ++ करता है, और यह पूरी तरह से स्पष्ट है कि यहां क्या हो रहा है। क्योंकि आप प्रत्येक बिंदु पर विफलता के लिए स्पष्ट रूप से परीक्षण कर रहे हैं, जिससे विशिष्ट लॉगिंग या त्रुटि से निपटने में प्रत्येक स्थान पर त्रुटि डालना आसान हो सकता है।
यदि आप थोड़ा मैक्रो जादू नहीं करते हैं, तो आप स्टैक के निशान के साथ लॉगिंग त्रुटियों जैसी अन्य चीजों को करते हुए इसे और अधिक संक्षिप्त बना सकते हैं। उदाहरण के लिए:
#include <assert.h>
#include <stdio.h>
#include <string.h>
#define TRY( X, LABEL ) do { if ( ( X ) ) { fprintf( stderr, "%s:%d: Statement '" #X "' failed! %d, %s\n", __FILE__, __LINE__, ret, strerror( ret ) ); goto LABEL; } while ( 0 )
typedef int errcode;
errcode init_or_fail( foo *f, goo *g, poo *p, loo *l )
{
errcode ret = 0;
TRY( ret = foo_init( f ), FAIL );
TRY( ret = goo_init( g ), FAIL_F );
TRY( ret = poo_init( p ), FAIL_G );
TRY( ret = loo_init( l ), FAIL_P );
assert( 0 == ret );
goto END;
/* error handling and return */
FAIL_P:
poo_fini( p );
FAIL_G:
goo_fini( g );
FAIL_F:
foo_fini( f );
FAIL:
assert( 0 != ret );
END:
return ret;
}
बेशक, यह सी + + अपवादों के रूप में सुरुचिपूर्ण नहीं है। उदाहरण के लिए, इस तरह से एक फ़ंक्शन के भीतर ढेरों से निपटने में कई त्रुटि को नाकाम करना बहुत साफ नहीं है। इसके बजाय, आप शायद उन लोगों को स्वयं के उप-कार्यों में तोड़ना चाहते हैं जो इसी तरह त्रुटियों को संभालते हैं, इस तरह से स्पष्ट रूप से शुरू करते हैं।
यह भी केवल एक ही कार्य के भीतर काम करता है और जब तक उच्च स्तर के कॉलर्स समान स्पष्ट त्रुटि वाले लॉजिक को लागू नहीं करते, तब तक स्टैक को जंप नहीं करते रहेंगे, जबकि C ++ अपवाद केवल स्टैक को ऊपर कूदने तक रहेगा, जब तक कि यह एक उपयुक्त हैंडलर न मिल जाए। न ही यह आपको एक मनमाना प्रकार फेंकने की अनुमति देता है, बल्कि केवल एक त्रुटि कोड है।
व्यवस्थित रूप से इस तरह से कोडिंग करना (यानी - एकल प्रविष्टि और एकल निकास बिंदु के साथ) पूर्व और पोस्ट ("अंत") तर्क को सम्मिलित करना बहुत आसान बनाता है जो कि किसी भी मामले को निष्पादित नहीं करेगा। आपने END लेबल के बाद अपना "अंततः" तर्क दिया।