क्या हमें C में निकास () का उपयोग करना चाहिए?


80

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

मुझे दिलचस्पी थी कि सी में यह स्थिति कैसे है? क्या इसी तरह के मुद्दे सी में भी लागू हैं? मुझे लगा कि C में हम कंस्ट्रक्टर / डिस्ट्रक्टर्स का उपयोग नहीं करते हैं, स्थिति C में भिन्न हो सकती है। इसलिए exitC में उपयोग करना ठीक है?

मैंने नीचे जैसे फ़ंक्शंस देखे हैं, जो मुझे कुछ मामलों में उपयोग करने के लिए ठीक लगते हैं, लेकिन अगर हमें सी के साथ इसी तरह के मुद्दे हैं exit, तो सी ++ के साथ ऊपर वर्णित है? (जो एक अच्छा विचार नहीं नीचे के रूप में कार्यों का उपयोग करना होगा।)


2
"वस्तुओं के विनाशकों को नहीं कहा जाएगा" - यह पूरी तरह से सही नहीं है (देखें: cplusplus.com/reference/cstdlib/exit )। आप quick_exit के बारे में सोच रहे हैं (देखें: cplusplus.com/reference/cstdlib/quick_exit/?kw=quick_exit )।
कोडर

आपके पास कुछ ऑपरेटिंग सिस्टम विशिष्ट मुद्दे भी हो सकते हैं, जैसे POSIX और लिनक्स पर सिग्नल की पारंपरिक भूमिका SIGTERM.... अच्छी तरह से व्यवहार किए गए सर्वर से यह अच्छी तरह से संभालने की उम्मीद है। और आपको इसका उपयोग करने से बचना चाहिए SIGKILL(अर्थात kill -TERMबाद में kill -QUITऔर फिर बाद में kill -KILL
सिसडमिन के

20
स्टैक ओवरफ्लो शुरू होने के लगभग 7 साल बाद यह डुप्लिकेट कैसे नहीं है?
पीटर मोर्टेंसन

7
@PeterMortensen: यह आश्चर्य की बात है, लेकिन मुझे एक अच्छे विकल्प के बारे में पता नहीं है जो यह डुप्लिकेट करता है। फ़ंक्शन का उच्च-मतदान उपयोगexit() जर्मे नहीं है (और उच्च मत गणना आश्चर्यजनक है - यह एक अच्छा सवाल नहीं है)। मुझे C में निकास () फ़ंक्शन का उपयोग क्यों नहीं करना चाहिए? यदि वह इस प्रश्न के कैलिबर का उत्तर देता तो अच्छा उम्मीदवार होता। यह नहीं है; इस के एक डुप्लिकेट के रूप में एक रिवर्स पास उपयुक्त है - और मैंने इसे किया है।
जोनाथन लेफ़लर

मुझे यकीन नहीं है कि आप त्रुटि के मामले में 'प्रिंटफ' का उपयोग करना चाहते हैं। फ़ंक्शन बफ़र्स का उपयोग करता है, लेकिन यदि आपके पास स्मृति भ्रष्टाचार है, तो वे बफ़र्स अच्छे नहीं हो सकते हैं। आप सिर्फ 'राइट (2, "त्रुटि:", 7) का उपयोग करना चाह सकते हैं; लिखना (2, संदेश, स्ट्रलेन (संदेश));
एलेक्स

जवाबों:


82

इसके बजाय abort(), exit()C में फ़ंक्शन को "ग्रेसफुल" निकास माना जाता है।

C11 (N1570) 7.22.4.4/p2 से बाहर निकलने का कार्य (जोर मेरा):

exitसमारोह का कारण बनता है सामान्य कार्यक्रम समाप्ति होने के लिये।

मानक 7.22.4.4/p4 में यह भी कहता है कि:

इसके बाद, अलिखित बफ़र्ड डेटा वाली सभी खुली धाराएँ फ़्लश हो जाती हैं , सभी खुली धाराएँ बंद हो जाती हैं , और tmpfileफ़ंक्शन द्वारा बनाई गई सभी फ़ाइलें निकाल दी जाती हैं।

यह भी 7.21.3 / p5 फ़ाइलें देखने लायक है :

यदि mainफ़ंक्शन अपने मूल कॉलर पर लौटता है, या यदि exit फ़ंक्शन को कॉल किया जाता है, तो प्रोग्राम समाप्ति से पहले सभी खुली फाइलें बंद हो जाती हैं (इसलिए सभी आउटपुट स्ट्रीम फ्लश हो जाती हैं)। कार्यक्रम समाप्ति के अन्य मार्ग, जैसे abortफ़ंक्शन को कॉल करना, सभी फ़ाइलों को ठीक से बंद करने की आवश्यकता नहीं है।

हालाँकि, जैसा कि नीचे टिप्पणी में कहा गया है कि आप यह नहीं मान सकते हैं कि यह हर दूसरे संसाधन को कवर करेगा , इसलिए आपको atexit()व्यक्तिगत रूप से उनकी रिहाई के लिए कॉलबैक का सहारा लेना और परिभाषित करना पड़ सकता है । वास्तव में यह वैसा ही है जैसा कि करने atexit()का इरादा है, जैसा कि 7.22.4.2/p2 में कहा गया है एटैक्सिट फ़ंक्शन :

atexitसमारोह रजिस्टरों समारोह द्वारा की ओर इशारा किया func, सामान्य कार्यक्रम समाप्ति पर बहस के बिना कहा जाता है।

विशेष रूप से, सी मानक ठीक से यह नहीं कहता है कि आवंटित भंडारण अवधि (यानी malloc()) की वस्तुओं का क्या होना चाहिए , इस प्रकार आपको यह जानने की आवश्यकता है कि यह विशेष कार्यान्वयन पर कैसे किया जाता है। आधुनिक, होस्ट-ओरिएंटेड OS के लिए, यह संभावना है कि सिस्टम इसका ध्यान रखेगा, लेकिन फिर भी आप अपने आप को Valgrind जैसे मेमोरी डीबगर्स को चुप कराने के लिए इसे संभालना चाह सकते हैं ।


3
यह मुझे सही उत्तर लगता है। एक सॉकेट कनेक्शन बाहर निकलने पर बंद कर दिया है क्योंकि प्रक्रिया समाप्त होने के सभी फाइल वर्णनकर्ता या नहीं, के साथ खुला बंद कर देता है stdio, यानी एक के बराबर है close()एफडी पर। मैं नहीं जानता कि किस मायने में @BlueMoon को लगता है कि यह गलत है, लेकिन यह किसी कॉल से कम गलत नहीं है close(), और अगर आगे क्लीयर-अप की आवश्यकता है, तो ठीक यही atexit()है।
abligh

1
@ बारिघ आधुनिक OS उस प्रक्रिया से जुड़े सभी fds को बंद कर देंगे; लेकिन यह कुछ क्रूर और मानक नहीं है (ब्लू मून जो कह रहा है)।
edmz

3
@ अगर आगे क्लीयर की जरूरत atexit()हो तो इस्तेमाल किया जा सकता है। exit()खुद का उपयोग करने returnसे ज्यादा क्रूर नहीं है main()
अबू

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

यह अच्छा होगा यदि आप संभव को जोड़ सकते हैं-अपने उत्तर में कि किस प्रकार के संसाधनों को जारी करने की आवश्यकता हो सकती है atexit, अन्यथा यह ठीक है। @BlueMoon: मुझे नहीं लगता कि फ़ंक्शन का उपयोग करना जैसे कि dieकोई प्रोग्राम नहीं कर सकता है, कई मौकों पर कोई भी इसका उपयोग करना चाह सकता है। अन्यथा वास्तव में, आप इसे केवल रिटर्न वैल्यू, आदि का उपयोग करके भी संभाल सकते हैं
gmoniava

23

हां, exitसी में उपयोग करना ठीक है ।

सभी बफ़र्स और सुशोभित क्रमिक बंद सुनिश्चित करने के लिए, इस फ़ंक्शन का उपयोग करने की सिफारिश की जाएगी atexit, इस पर अधिक जानकारी यहां

एक उदाहरण कोड इस तरह होगा:

अब, जब भी exitबुलाया जाता है, तो कार्य cleanupनिष्पादित हो जाएगा, जो सुंदर शटडाउन को साफ कर सकता है, बफ़र्स को साफ कर सकता है, मेमोरी आदि।


@IlmariKaronen आवंटित स्मृति किसी भी तरह से स्वचालित रूप से नियंत्रित नहीं की जाती है। यह ओएस है जो यह सुनिश्चित कर सकता है कि मेमोरी ओएस पर वापस आ जाए। ग्रेज़गोरज़ स्ज़ेटकोव्स्की का तर्क आपके बयान का विरोध कर रहा है: विशेष रूप से, सी मानक ठीक से यह नहीं कहता है कि आवंटित भंडारण अवधि (iemalloc ()) की वस्तुओं के साथ क्या होना चाहिए, इस प्रकार आपको यह जानना आवश्यक है कि यह विशेष कार्यान्वयन के लिए कैसे किया जाता है। आधुनिक, होस्ट-ओरिएंटेड OS के लिए, यह संभावना है कि सिस्टम इसका ध्यान रखेगा, लेकिन फिर भी आप अपने आप को Valgrind जैसे मेमोरी डीबगर्स को चुप कराने के लिए इसे संभालना चाह सकते हैं।
यह

15

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


8
यह उत्तर "प्रोग्रामिंग भाषा न सीखें, प्रोग्राम कैसे सीखें" इसका एक बड़ा उदाहरण है। आप आम तौर पर एक अलग भाषा चुनकर समस्या को समझने से बच सकते हैं।
केरेक एसबी

10
मैं इसे गलत मानता हूं। यदि आप कॉल करते हैं exit()(इसके बजाय _exit()) atexitरूटीन कहा जाता है और stdioबफरिंग डिस्क में फ्लश हो जाती है। exit()कार्यक्रम के एक क्रम से बाहर निकलने की अनुमति देने के लिए ठीक है।
abligh

2
उदाहरण के लिए @abligh रीयल टाइम सिस्टम, फ्री मैक्लो'ड मेमोरी को मुक्त नहीं करता है, उदाहरण के लिए, जिसके परिणामस्वरूप लीक होता है। POSIX साझा की गई मेमोरी एक और उदाहरण है। इसलिए यह सी मानक का सख्ती से पालन करने के बजाय पर्यावरण पर निर्भर करता है।
PP

2
@ बारिघ: सभी संसाधन मानक पुस्तकालय उपलब्ध नहीं हैं। जब आप निश्चित रूप से सही होते हैं कि मानक पुस्तकालय कुछ गारंटी देता है, तब भी आपको अपने कार्यक्रम के वैश्विक नियंत्रण प्रवाह और इसके प्रत्येक भाग की जिम्मेदारियों के बारे में सोचने की जरूरत है , और सुनिश्चित करें कि प्रत्येक लंबित जिम्मेदारी को उचित रूप से निपटाया जाए। "संसाधन" शब्द इस सामान्य धारणा के लिए एक संक्षिप्त शब्द है और किसी विशेष पुस्तकालय को स्थानांतरित करता है, और संसाधनों को संभालना अंततः प्रोग्रामर की जिम्मेदारी है। जैसी सुविधाएं atexitमदद कर सकती हैं, हालांकि वे हमेशा उचित नहीं होती हैं।
केर्रेक एसबी

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

10

का उपयोग करना exit()ठीक है

कोड डिजाइन के दो प्रमुख पहलू जिनका अभी तक उल्लेख नहीं किया गया है, वे हैं 'थ्रेडिंग' और 'लाइब्रेरी'।

एकल-थ्रेडेड प्रोग्राम में, कोड में आप उस प्रोग्राम को लागू करने के लिए लिख रहे हैं, का उपयोग exit()करना ठीक है। मेरे कार्यक्रम नियमित रूप से इसका उपयोग करते हैं जब कुछ गलत हो जाता है और कोड ठीक नहीं हो रहा है।

परंतु…

हालाँकि, कॉलिंग exit()एकतरफा कार्रवाई है जिसे पूर्ववत नहीं किया जा सकता है। इसीलिए why थ्रेडिंग ’और 'लाइब्रेरियों’ दोनों के लिए सावधानीपूर्वक विचार की आवश्यकता है।

पिरोया गया कार्यक्रम

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

लाइब्रेरी कोड

और यह कि 'कार्यक्रम के डिजाइन का संज्ञान' खंड, पुस्तकालयों में कोड के लिए भी लागू होता है। कॉल करने के लिए सामान्य प्रयोजन लाइब्रेरी फ़ंक्शन के लिए यह बहुत कम सही है exit()। यदि मानक C लाइब्रेरी फ़ंक्शंस में से कोई एक त्रुटि के कारण वापस लौटने में विफल रहा, तो आप उचित रूप से परेशान होंगे। (जाहिर है, कार्यों की तरह exit(), _Exit(), quick_exit(), abort()नहीं वापसी करने का इरादा कर रहे हैं, अलग-अलग है।) सी पुस्तकालय में कार्यों इसलिए या तो "असफल नहीं हो सकता" या एक त्रुटि संकेत किसी भी तरह वापस जाएँ। यदि आप एक सामान्य उद्देश्य पुस्तकालय में जाने के लिए कोड लिख रहे हैं, तो आपको अपने कोड के लिए त्रुटि हैंडलिंग रणनीति पर सावधानीपूर्वक विचार करने की आवश्यकता है। यह उन कार्यक्रमों की त्रुटि हैंडलिंग रणनीतियों के साथ फिट होना चाहिए जिनके साथ इसका उपयोग करने का इरादा है, या त्रुटि हैंडलिंग को विन्यास योग्य बनाया जा सकता है।

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

मेरे पास कई अन्य पुस्तकालय कार्य हैं, और उनमें से कई अच्छे "stderr.h"त्रुटि रिपोर्टिंग के लिए कोड पर निर्भर हैं । यह एक डिजाइन निर्णय है जो मैंने किया है और एक है जो मैं ठीक हूं। लेकिन जब त्रुटियों को बाहर निकलने वाले कार्यों के साथ सूचित किया जाता है, तो यह लाइब्रेरी कोड की सामान्य उपयोगिता को सीमित करता है। यदि कोड त्रुटि रिपोर्टिंग फ़ंक्शन को कॉल करता है जो बाहर नहीं निकलता है, तो फ़ंक्शन में मुख्य कोड पथ को त्रुटि रिटर्न से निपटने के लिए है - उन्हें पता लगाने और कॉलिंग कोड में एक त्रुटि संकेत को रिले करने के लिए।


मेरी त्रुटि रिपोर्टिंग पैकेज के लिए कोड मेरे में उपलब्ध है SOQ फ़ाइलों के रूप में GitHub पर (स्टैक ओवरफ़्लो प्रश्न) भंडार stderr.cऔर stderr.hमें src / libsoq उप-निर्देशिका।


यह अच्छी तरह से बताया गया है। आप यहां लाइब्रेरी का एक उदाहरण देख सकते हैं जो कॉल करता है abort()जब वह malloc()या तो मेमोरी को आवंटित करने की realloc()कल्पना करता है या , कल्पना करें, कि आपके पास एक एप्लिकेशन है, जो कि 100 पुस्तकालयों के साथ लिंक करता है और आपको आश्चर्य होता है कि आपके आवेदन को किसने और कैसे क्रैश किया। इससे अधिक मुझे abort()उनके दस्तावेज़ में कोई उल्लेख नहीं मिला है (लेकिन मुझे गलत मत समझिए। यह अपने उद्देश्य के लिए महान पुस्तकालय है)।
ग्रेज़गोरज़ स्ज़ेपकोव्स्की

@GrzegorzSzpetkowski और यह भी मैन्युअल रूप से फोन करने वाले को fprinting के बाद फ्लश फोन नहीं करता है। आउच!
यह

1
@ इस: ऐसा करने की जरूरत नहीं होनी चाहिए। से उत्पादन stderrआम तौर पर लाइन बफर है। यदि आउटपुट एक नई रेखा के साथ समाप्त होता है, तो इसे सिस्टम द्वारा वैसे भी फ्लश किया जाएगा।
जोनाथन लेफ़लर 2

@JonathanLeffler उपयोगकर्ता पर भरोसा, स्मार्ट चाल नहीं।
यह

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

6

इसके exitअलावा अन्य कार्यों में बचने का एक कारण main()यह है कि आपके कोड को संदर्भ से बाहर ले जाया जा सकता है। याद रखें, निकास एक प्रकार का गैर स्थानीय नियंत्रण प्रवाह है । अकारण अपवादों की तरह।

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

या आप इसे एक एम्बेडेड सिस्टम पर चला सकते हैं। बाहर निकलने के लिए कहीं नहीं है , पूरी चीज एक while(1)लूप में चलती है main()। यह मानक पुस्तकालय में भी परिभाषित नहीं किया जा सकता है।


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

3
एक नहीं बल्कि पुलाव सादृश्य। C उन चीज़ों से भरा हुआ है जिन्हें किया जा सकता है लेकिन शायद इससे बचना चाहिए। इसलिए IOCCC का अस्तित्व। ध्यान दें कि मेरा पोस्ट "नहीं करना चाहिए" नहीं कहता है।
pjc50

2

आप जो कर रहे हैं उसके आधार पर, सी में प्रोग्राम से बाहर निकलने का सबसे तार्किक तरीका हो सकता है। मुझे पता है कि कॉलबैक की चेन को सही तरीके से काम करने के लिए यह जाँचना बहुत उपयोगी है। हाल ही में उपयोग किए गए कॉलबैक का यह उदाहरण लें:

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


-1

यह एक बड़ी परियोजना में भयानक है जब कोई भी कोड coredump को छोड़कर बाहर निकल सकता है। एक ऑनलाइन सर्वर को बनाए रखने के लिए ट्रेस बहुत आयात होता है।

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