मेमोरियल पर बेज़ेरो का उपयोग क्यों करें?


156

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

मैं यहाँ देखता हूँ: http://fdiv.net/2009/01/01/14/memset-vs-bzero-ultimate-showdown जो bzeroकेवल शून्य मेमोरी होने जा रहा है, इस तथ्य के कारण अधिक कुशल है, इसलिए यह नहीं करता है कोई अतिरिक्त जाँच करनी होगी जो memsetकर सकते हैं। यह अभी भी जरूरी नहीं है कि बिल्कुल memsetशून्य स्मृति के लिए उपयोग नहीं करने के लिए एक कारण की तरह लगता है ।

bzeroमाना जाता है कि पदावनत, और इसके अलावा एक मानक सी फ़ंक्शन नहीं है। मैनुअल के अनुसार, इस कारण memsetसे अधिक पसंद किया जाता है bzero। तो क्यों आप अभी भी उपयोग करना चाहते bzeroहैं memset? सिर्फ दक्षता हासिल करने के लिए, या यह कुछ और है? इसी तरह, इससे memsetअधिक लाभ क्या हैं bzeroकि यह नए कार्यक्रमों के लिए वास्तव में पसंदीदा विकल्प है?


28
"मेमोरियल पर बेज़ेरो का उपयोग क्यों करें?" - नहीं। Memset मानक है, Bzero नहीं है।

30
Bzero एक BSDism () है। memset () asi-c है। आजकल, बेज़ेरो () को संभवतः एक मैक्रो के रूप में लागू किया जाएगा। अपने प्रोफेसर से खुद को शेव करने और कुछ किताबें पढ़ने को कहें। दक्षता एक संगीन-तर्क है। एक syscall या संदर्भ-स्विच आसानी से हजारों घड़ी की टिकियों की लागत ले सकता है, एक बफर बस से अधिक गति से गुजरता है। यदि आप नेटवर्क-प्रोग्राम ऑप्टिमाइज़ करना चाहते हैं: syscalls की संख्या को कम करें (बड़ी मात्रा में पढ़ / लिखकर)
वाइल्डप्लास्सर

7
यह विचार memset"थोड़ा और अधिक जाँच के कारण थोड़ा कम कुशल हो सकता है" निश्चित रूप से समय से पहले अनुकूलन का मामला है: जो कुछ भी लाभ आप सीपीयू निर्देश को छोड़ने से देख सकते हैं या दो इसके लायक नहीं हैं जब आप अपने पोर्टेबिलिटी को खतरे में डाल सकते हैं कोड। bzeroअप्रचलित है, और इसका उपयोग न करने के लिए पर्याप्त कारण है।
dasblinkenlight

4
अक्सर, आप इसके बजाय एक initializer `= {0}` जोड़ सकते हैं, और फ़ंक्शन को कॉल नहीं कर सकते। यह तब आसान हो गया जब शताब्दी के मोड़ के आसपास C ने स्थानीय चरों की अप-फ्रंट घोषणा की आवश्यकता बंद कर दी। कुछ सही मायने में पुराने पेपरवेयर अभी भी पिछली सदी में गहरे अटके हुए हैं।
एमएसल्टर्स

1
@SSAnne नहीं, लेकिन यह सबसे अधिक संभावना है कि वह जिस पुस्तक से प्रभावित था, उसके लिए एक अनुशंसित पुस्तक से उत्पन्न हुआ है, जैसा कि नीचे दिए गए उत्तरों में से एक में बताया गया है: stackoverflow.com/a/17097072/1428743
PseudoPshehe

जवाबों:


152

मैं पसंद करने के लिए किसी भी कारण नहीं दिख रहा है bzeroखत्म हो गया memset

memsetएक मानक C फ़ंक्शन है जबकि bzeroC मानक फ़ंक्शन कभी नहीं हुआ। औचित्य शायद इसलिए है क्योंकि आप फ़ंक्शन का उपयोग करके समान कार्यक्षमता प्राप्त कर सकते हैं memset

अब दक्षता के संबंध में, कम्पाइलर gccबिलिन कार्यान्वयन का उपयोग करते हैं, memsetजिसके लिए किसी स्थिरांक 0का पता चलने पर किसी विशेष कार्यान्वयन पर स्विच किया जाता है। glibcजब बिल्डिंग्स अक्षम होती हैं तो उसी के लिए ।


धन्यवाद। यह समझ में आता है। मुझे पूरा यकीन था कि memsetइस मामले में हमेशा इस्तेमाल किया जाना चाहिए, लेकिन इस बात से उलझन में था कि हम इसका इस्तेमाल क्यों नहीं कर रहे हैं। मेरे विचारों को स्पष्ट करने और पुन: पुष्टि करने के लिए धन्यवाद।
स्यूडोस्पीक

1
मुझे टूटी हुई bzeroकार्यान्वयन के साथ कई समस्याएं हैं । गुटनिरपेक्ष सरणियों पर यह प्रदान की गई लंबाई का निरीक्षण करते थे और थोड़ा और बाइट्स शून्य करते थे। स्विच करने के बाद कभी ऐसा कोई मुद्दा नहीं था memset
rustyx

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

69

मैं अनुमान लगा रहा हूं कि आपने डब्लू। रिचर्ड स्टीवंस द्वारा यूनिक्स नेटवर्क प्रोग्रामिंग का इस्तेमाल किया था (या आपका शिक्षक उससे प्रभावित था) । वह ज्यादातर अप-टू-डेट संस्करण के bzeroबजाय अक्सर उपयोग करता है memset। पुस्तक इतनी लोकप्रिय है, मुझे लगता है कि यह नेटवर्क प्रोग्रामिंग में एक मुहावरा बन गया है यही कारण है कि आप अभी भी इसका इस्तेमाल करते हैं।

मैं memsetबस के साथ रहना होगा क्योंकि bzeroपदावनत है और पोर्टेबिलिटी कम कर देता है। मुझे संदेह है कि आप किसी एक पर दूसरे का उपयोग करने से कोई वास्तविक लाभ देखेंगे।


4
आप सही होंगे। हमें इस पाठ्यक्रम के लिए पाठ्यपुस्तकों की आवश्यकता नहीं थी, लेकिन मैंने सिर्फ पाठ्यक्रम की फिर से जाँच की और UNIX नेटवर्क प्रोग्रामिंग को वास्तव में वैकल्पिक संसाधन के रूप में सूचीबद्ध किया गया है। धन्यवाद।
छद्मपीसाइ

9
यह वास्तव में इससे भी बदतर है। इसे POSIX.1-2001 में पदावनत किया गया और POSIX.1-2008 में हटा दिया गया।
पैक्सिडाब्लो

9
डब्ल्यू। रिचर्ड स्टीवंस द्वारा यूनिक्स नेटवर्क प्रोग्रामिंग के तीसरे संस्करण के पृष्ठ 8 को उद्धृत करते हुए - वास्तव में, टीसीपीवी 3 के लेखक ने पहली छपाई के 10 घटनाओं में याद करने के लिए दूसरे और तीसरे तर्क को स्वैप करने की गलती की। AC कंपाइलर इस त्रुटि को पकड़ नहीं सकता क्योंकि दोनों घटनाएँ समान हैं ... यह एक त्रुटि थी, और bzero का उपयोग करने से बचा जा सकता है, क्योंकि bzero को दो तर्कों की अदला-बदली हमेशा C कंपाइलर द्वारा पकड़ा जाएगा यदि फ़ंक्शन प्रोटोटाइप का उपयोग किया जाता है। हालाँकि जैसा कि paxdiablo ने बताया, bzero को हटा दिया गया है।
हारून न्यूटन

@AaronNewton, आपको माइकल के उत्तर के साथ जोड़ना चाहिए क्योंकि यह पुष्टि करता है कि उसने क्या कहा।
Synetech

52

मेमोरी को शून्य bzero()पर memset()सेट करने के लिए मेरे पास एक लाभ यह है कि गलती होने की संभावना कम है।

एक से अधिक बार मैं एक बग के पार आया हूँ जो ऐसा दिखता था:

memset(someobject, size_of_object, 0);    // clear object

कंपाइलर शिकायत नहीं करेगा (हालांकि कुछ कंपाइलरों पर कुछ चेतावनी स्तरों को क्रैक कर सकता है) और इसका असर यह होगा कि मेमोरी क्लियर नहीं होती है। क्योंकि यह ऑब्जेक्ट को कचरा नहीं करता है - यह सिर्फ इसे अकेला छोड़ देता है - एक सभ्य मौका है कि बग स्पष्ट रूप से प्रकट नहीं हो सकता है।

तथ्य यह bzero()है कि मानक नहीं है एक मामूली अड़चन है। (एफडब्ल्यूआईडब्ल्यू, मुझे आश्चर्य नहीं होगा अगर मेरे कार्यक्रमों में अधिकांश फ़ंक्शन गैर-मानक हैं; वास्तव में इस तरह के कार्य लिखना मेरे काम का प्रकार है)।

यहाँ एक अन्य जवाब के लिए एक टिप्पणी में, हारून न्यूटन ने यूनिक्स नेटवर्क प्रोग्रामिंग, वॉल्यूम 1, 3 संस्करण द्वारा स्टीवंस, एट अल, धारा 1.2 (जोर जोड़ा) से निम्नलिखित का हवाला दिया:

bzeroANSI C फ़ंक्शन नहीं है। यह शुरुआती बर्कली नेटवर्किंग कोड से लिया गया है। फिर भी, हम ANSI C memsetफ़ंक्शन के बजाय पूरे पाठ में इसका उपयोग करते हैं, क्योंकि bzero(केवल memsetतीन तर्कों के साथ ) केवल दो तर्कों के साथ याद रखना आसान है । लगभग हर विक्रेता जो सॉकेट एपीआई का समर्थन करता है bzero, वह भी प्रदान करता है , और यदि नहीं, तो हम अपने unp.hहेडर में एक मैक्रो परिभाषा प्रदान करते हैं ।

दरअसल, टीसीपी 3 के लेखक [टीसीपी / आईपी इलस्ट्रेटेड, वॉल्यूम 3 - स्टीवंस 1996] ने memsetपहली प्रिंटिंग में 10 घटनाओं में दूसरे और तीसरे तर्क को स्वैप करने की गलती की । AC कंपाइलर इस त्रुटि को नहीं पकड़ सकता क्योंकि दोनों तर्क एक ही प्रकार के हैं। (वास्तव में, दूसरा तर्क एक है intऔर तीसरा तर्क है size_t, जो आम तौर पर एक है unsigned int, लेकिन क्रमशः निर्दिष्ट मान, 0 और 16, अन्य प्रकार के तर्क के लिए अभी भी स्वीकार्य हैं।) कॉल memsetअभी भी काम किया है, क्योंकि केवल। सॉकेट कार्यों में से कुछ को वास्तव में आवश्यकता होती है कि इंटरनेट सॉकेट एड्रेस संरचना के अंतिम 8 बाइट्स को 0. पर सेट किया जाना चाहिए। फिर भी, यह एक त्रुटि थी, और जिसे उपयोग करके टाला जा सकता था bzero, क्योंकि bzeroफ़ंक्शन के प्रोटोटाइप का उपयोग किए जाने पर दो तर्कों को स्वैप करने से हमेशा C कंपाइलर द्वारा पकड़ा जाएगा।

मेरा यह भी मानना ​​है कि अधिकांश कॉल memset()शून्य मेमोरी के हैं, इसलिए उस उपयोग मामले के अनुरूप एपीआई का उपयोग क्यों नहीं किया जाता है?

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


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

5
मुझे लगता है कि यह एक तर्क है जिसे कक्षा के बाहर भी बनाया जा सकता है - मैंने इस बग को उत्पादन कोड में देखा है। यह मुझे एक आसान गलती के रूप में मारता है। मैं यह भी अनुमान लगाऊंगा कि अधिकांश memset()कॉल केवल मेमोरी के एक ब्लॉक को शून्य करने के लिए हैं, जो मुझे लगता है कि इसके लिए एक और तर्क है bzero()bzero()वैसे भी स्टैंड में 'बी' क्या है ?
माइकल बूर

7
+1। यह memset"बफर, बफर_साइज़" के आदेश के एक सामान्य पैरामीटर का उल्लंघन करता है जो इसे विशेष रूप से त्रुटि-ग्रस्त IMO बनाता है।
jamesdlin

पास्कल में वे इसे "फिलचर" कहकर टाल देते हैं और यह एक चार ले लेता है। अधिकांश C / C ++ कंपाइलर उस एक को उठा लेते हैं। जो मुझे आश्चर्यचकित करता है कि कंपाइलर क्यों नहीं कहते हैं "आप एक 32/64 बिट पॉइंटर पास कर रहे हैं जहां एक बाइट की उम्मीद है" और आपको कंपाइलर त्रुटियों में मजबूती से किक करता है।
मोटो

1
@ दूसरा और तीसरा तर्क गलत क्रम में हैं; फंक्शन कॉल का मतलब कुछ भी नहीं है
Ichthyo

4

Bzero बनाम memset तर्क के बारे में कुछ उल्लेख करना चाहता था। लेट्रेस स्थापित करें और फिर यह हुड के नीचे क्या करता है की तुलना करें। Linux पर libc6 (2.19-0ubuntu6.6) के साथ, किए गए कॉल बिल्कुल (जैसे ltrace ./test123) हैं:

long m[] = {0}; // generates a call to memset(0x7fffefa28238, '\0', 8)
int* p;
bzero(&p, 4);   // generates a call to memset(0x7fffefa28230, '\0', 4)

मुझे बताया गया है कि जब तक मैं libc के गहरे आंत्र या कर्नेल / syscall इंटरफ़ेस की किसी भी संख्या में काम कर रहा हूं, मुझे उनके बारे में चिंता करने की आवश्यकता नहीं है। मुझे इस बारे में चिंता करनी चाहिए कि कॉल बफर को शून्य करने की आवश्यकता को पूरा करता है। दूसरों ने इस बारे में उल्लेख किया है कि कौन सा दूसरे पर बेहतर है इसलिए मैं यहां रुकूंगा।


ऐसा इसलिए होता है क्योंकि GCC के कुछ वर्जन memset(ptr, 0, n)जब देखते हैं तो उनके लिए कोड निकल जाएंगे bzero(ptr, n)और वे इसे इनलाइन कोड में नहीं बदल सकते।
zwol

@zwol यह वास्तव में एक मैक्रो है।
एसएस ऐनी

1
@SSAnne gcc 9.3 मेरे कंप्यूटर पर सिस्टम हेडर में मैक्रोज़ की मदद के बिना, इस परिवर्तन को स्वयं करता है। extern void bzero(void *, size_t); void clear(void *p, size_t n) { bzero(p, n); }के लिए एक कॉल पैदा करता है memset। ( बिना किसी और चीज़ के stddef.hलिए शामिल करें size_tजो हस्तक्षेप कर सके।)
zwol

4

आपको शायद उपयोग नहीं करना चाहिएbzero , यह वास्तव में मानक C नहीं है, यह एक POSIX चीज थी।

और ध्यान दें कि शब्द "था" - इसे POSIX.1-2001 में पदावनत कर दिया गया था और POSIX.1-2008 में हटा दिया गया ताकि यह याद रहे कि आप मानक C फ़ंक्शन का उपयोग करके बेहतर हैं।


मानक C से आपका क्या अभिप्राय है? आपका मतलब है कि यह मानक सी लाइब्रेरी में नहीं पाया जाता है?
कोरे तुगे

@ कोरे, मानक सी का अर्थ है आईएसओ मानक और, हां, bzeroइसका हिस्सा नहीं है।
पैक्सडीब्लो

नहीं मेरा मतलब है, मुझे नहीं पता कि आप किसी भी मानक से क्या मतलब है। क्या ISO मानक का मतलब मानक C लाइब्रेरी है? वह भाषा आती है? न्यूनतम पुस्तकालय जिसे हम जानते हैं कि यह वहां होगा?
कोरे तुगे

2
@ कोरे, आईएसओ मानक संगठन है जो C मानक, वर्तमान C11 और पहले वाले C99 और C89 के लिए जिम्मेदार है। वे उन नियमों को पूरा करते हैं जिन्हें एक कार्यान्वयन सी के रूप में विचार करने के लिए पालन करना चाहिए। हां, यदि मानक कहता है कि एक कार्यान्वयन को अनिवार्य रूप से छूट प्रदान करनी चाहिए, तो यह आपके लिए होगा। अन्यथा, यह सी नहीं है
paxdiablo

2

मेमसेट फ़ंक्शन के लिए, दूसरा तर्क एक है intऔर तीसरा तर्क है size_t,

void *memset(void *s, int c, size_t n);

जो आम तौर पर एक है unsigned int, लेकिन अगर 0 and 16दूसरे और तीसरे तर्क के लिए जैसे मान गलत क्रम में 16 और 0 के रूप में दर्ज किए जाते हैं, तो, इस तरह की कॉल करने के लिए अभी भी काम कर सकता है, लेकिन कुछ भी नहीं करेगा। क्योंकि शुरू करने के लिए बाइट्स की संख्या के रूप में निर्दिष्ट किया गया है 0

void bzero(void *s, size_t n)

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


1
अगर आप कॉल को "इस आकार के लिए इस मान को इस मेमोरी में सेट करते हैं", या यदि आपके पास एक आईडीई है जो आपको प्रोटोटाइप देता है या भले ही आपको पता हो कि आपको क्या पता है, तो इस तरह की त्रुटि को भी परेशान होने से बचा जा सकता है। कर :-)
paxdiablo

सहमत हूं, लेकिन यह फ़ंक्शन उस समय बनाया गया था जब इस तरह के बुद्धिमान आईडीई समर्थन के लिए उपलब्ध नहीं थे।
हवलदार

2

संक्षेप में: memset तब और अधिक विधानसभा संचालन की आवश्यकता होती है bzero

यह स्रोत है: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown


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

6
यह केवल यह दर्शाता है कि स्मृतियों का एक बकवास कार्यान्वयन धीमा है। MacOS X और कुछ अन्य प्रणालियों पर, मेमसेट कोड का उपयोग करता है जो कि आपके द्वारा उपयोग किए जा रहे प्रोसेसर के आधार पर बूट समय पर सेट होता है, वेक्टर रजिस्टरों का पूर्ण उपयोग करता है, और बड़े आकार के लिए यह अंतिम बिट प्राप्त करने के लिए चतुर तरीकों से प्रीफ़ेक् ट निर्देशों का उपयोग करता है गति की।
gnasher729

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

2

आप इसे किसी भी तरह से पसंद करें। :-)

#ifndef bzero
#define bzero(d,n) memset((d),0,(n))
#endif

ध्यान दें कि:

  1. मूल bzeroरिटर्न कुछ नहीं देता है, memsetशून्य पॉइंटर ( d) देता है। यह परिभाषा में शून्य के लिए टाइपकास्ट जोड़कर तय किया जा सकता है।
  2. #ifndef bzeroमूल फ़ंक्शन को छुपाने से रोकता नहीं है, भले ही वह मौजूद हो। यह एक स्थूल के अस्तित्व का परीक्षण करता है। इससे बहुत भ्रम पैदा हो सकता है।
  3. किसी मैक्रो को फ़ंक्शन पॉइंटर बनाना असंभव है। bzeroफ़ंक्शन पॉइंटर्स के माध्यम से उपयोग करते समय , यह काम नहीं करेगा।

1
इसमें क्या दिक्कत है, @ लियर? मैक्रो के लिए सामान्य एंटीपैथी? या आप इस तथ्य को नापसंद करते हैं कि यह मैक्रो फ़ंक्शन के साथ भ्रमित हो सकता है (और संभवतः इसे छुपाता भी है)?
पेलेक

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

1
एक और विचार देने के बाद, मैं सहमत हूं कि यह वास्तव में एक बुरा समाधान है। अन्य बातों के अलावा, मुझे एक तकनीकी कारण मिला: bzeroफ़ंक्शन पॉइंटर्स के माध्यम से उपयोग करते समय , यह काम नहीं करेगा।
पेलेक

आपको वास्तव में अपने मैक्रो को इसके अलावा कुछ और कहना चाहिए था bzero। यह एक अत्याचार है।
दान बेचार

-2

मेमरी में 3 पैरामीटर लगते हैं, बेज़ेरो को मेमोरी में 2 की कमी होती है, अतिरिक्त पैरामीटर में 4 और बाइट्स लगेंगे और अधिकतर समय इटेल का उपयोग सब कुछ 0 पर सेट करने के लिए किया जाएगा

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