Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

सी एक्सटेंशन से रूबी विधियों को लागू करते समय मेमोरी लीक को रोकें

<पी> जेम उपयोगकर्ताओं के लिए मेमोरी लीक एक पीड़ादायक है। उन्हें ट्रैक करना कठिन है और इससे बुनियादी ढांचे की लागत महंगी हो सकती है।

<पी> सी एक्सटेंशन के भीतर मेमोरी लीक और भी बदतर है। आप रूबी में लीक खोजने के बारे में बहुत सारे टूल और लेख देखेंगे। हालाँकि, आपके पास C में आंतरिक तक समान पहुंच नहीं है।

<पी> rb_funcall का एक सहज प्रयोग मेमोरी लीक का कारण बन सकता है:rb_protect का उपयोग करना बहुत बेहतर है इसके बजाय. इसलिए, यदि आप सी एक्सटेंशनराइटर हैं, तो कृपया उन डेवलपर्स के लिए पढ़ें जो आपके रत्न का उपयोग करेंगे। <पी> आइए शुरू करें!

rb_funcall के साथ समस्या और सी

<पी> rb_funcall जब आपको रूबी और अपनी लाइब्रेरी के सी भागों के बीच इंटरैक्ट करने की आवश्यकता होती है, लेकिन केवल थोड़ा सी लिखने की आवश्यकता होती है, तो यह एक बेहतरीन टूल हो सकता है।

<पी> हालाँकि, जब आप rb_funcall चलाते हैं , अब आप सी में नहीं हैं जहां सब कुछ सीधा है। यदि फ़ंक्शन कहा जाता है तो आपको गंदे पानी में छोड़ा जा सकता है:

  1. रनटाइम के दौरान इसकी परिभाषा पूरी तरह से बदल जाती है
  2. कॉल उठाता है
<पी> नंबर 1 को पकड़ना सबसे आसान है। संभवतः आप एक सेगफ़ॉल्ट के साथ समाप्त हो जाएंगे, और यदि आपका परीक्षण सूट पर्याप्त रूप से पूरा हो गया है, तो आपको प्रकाशन से पहले इसे पकड़ लेना चाहिए।

<पी> हालाँकि, बाद वाला मेमोरी लीक का कारण बन सकता है और आपके कोडबेस को पढ़ना कठिन बना सकता है। आइए अब उस पर एक नज़र डालें।

रूबी में वृद्धि के कारण सी मेमोरी लीक हो रही है

<पी> रूबी का राइजिंग मैकेनिज्म कोड के कुछ हिस्सों के बीच एक स्कोप से पहले पैरेंट तक कूदता है जो त्रुटि पकड़ता है। इसे longjmp का उपयोग करके एमआरआई में लागू किया जाता है और setjmp .

<पी> यदि आप इसमें रुचि रखते हैं कि इसे कैसे बनाया जाता है, तो रूबी हैकिंग गाइड में मूल्यांकनकर्ता अध्याय पढ़ें। संक्षेप में, जब आप begin..ensure का उपयोग करते हैं ब्लॉक करें, आप setjmp() , और जब आप इस ब्लॉक के भीतर उठाते हैं, तो आप longjmp() सहेजे गए स्थान पर.

<पी> इसलिए यदि कोई फ़ंक्शन rb_funcall के साथ उठाया जाता है , इसके बाद कॉल किया गया C कोड कभी निष्पादित नहीं होता।

<पी> नीचे दिया गया उदाहरण संभावित रिसाव को दर्शाता है। यदि json_parse उठाता है, यह लीक हो जाएगा.

 <पी> बेशक, ऊपर दिया गया उदाहरण थोड़ा मूर्खतापूर्ण है - आप फ्रीिंग और रूबी प्रसंस्करण भागों को उल्टा कर सकते हैं। हालाँकि, यह हमेशा संभव नहीं होता है, और लंबे समय तक कार्य करने वाले निकाय अधिक आपस में जुड़ सकते हैं।

begin..ensure का उपयोग करना रूबी में

<पी> यदि आप रूबी का उपयोग कर रहे हैं, तो आप इसके बजाय begin..ensure का उपयोग करके उपरोक्त उदाहरण लिख सकते हैं :

 <पी> यह एपीआई rb_rescue के साथ सी में भी उपलब्ध है और rb_ensure :

 <पी> हालाँकि, यह थोड़ा बोझिल है, और यदि आप एक rescue जोड़ना चाहते हैं पार्टी को ब्लॉक करें, यह कम पठनीय हो जाता है। यदि आप begin..rescue..ensure..end का उपयोग करना चाहते हैं तो मैं पीटर झू की 'ए रूबिस्ट्स वॉक अलॉन्ग द सी-साइड (भाग 8):अपवाद और त्रुटि प्रबंधन' पढ़ने का सुझाव देता हूं। सी में एपीआई. 

rb_protect का उपयोग करना C

के लिए <पी> एक और विकल्प है. सबसे पहले, आइए देखें कि यह रूबी में कैसा दिख सकता है:

 <पी> रूबी में यह अजीब लगता है, लेकिन यह सी के लिए बहुत उपयुक्त वर्कफ़्लो है। एमआरआई में इसके लिए एक एपीआई है, rb_protect , और C फ़ंक्शन इस तरह दिखता है:

 <पी> उपरोक्त विधि फ्रीएवरीथिंग होने के बाद रूबी त्रुटि को फिर से बढ़ा देगी।

<पी> ध्यान दें कि हम एम्प्टी rescue का उपयोग करके त्रुटि को अनदेखा करना भी चुन सकते हैं रूबी में ब्लॉक:

 <पी> चेतावनी: यदि आप त्रुटि नहीं उठाते हैं, तो rb_set_errinfo(Qnil) यह कदम महत्वपूर्ण है ताकि आप किसी त्रुटि के बारे में जानकारी उपलब्ध न रखें जिसके बारे में उपयोगकर्ताओं को पता नहीं होना चाहिए।  <पी> या, आप सशर्त रूप से rescue My::Error जैसी त्रुटि उठाना चुन सकते हैं :

 <पी> आप वास्तव में rb_errinfo() पर विचार कर सकते हैं $! के समान ग्लोबलवेरिएबल.

<पी> यह सब बढ़िया है, लेकिन जब यह घटकर एक rb_funcall हो जाता है केवल, हम उस एपीआई को सरल बना सकते हैं।

<पी> rb_protect का उपयोग करने के पीछे का समग्र विचार एपीआई जब उठाने का कार्य होता है तो पठनीयता को बढ़ाना होता है। आपको यह जांचने की ज़रूरत नहीं है कि फ़ंक्शन बढ़ सकता है या नहीं, आप मान लें कि यह बढ़ सकता है, और उस पर काम करने के लिए राज्य का उपयोग करें।

rb_protect_funcall प्रस्ताव

<पी> आइए rb_funcall को अलग करें , क्योंकि यह एकमात्र खतरनाक है उपयोग करने की विधि. यहां एक एपीआई है जो ऐसा करेगी:

 <पी> यह एपीआई rb_funcall के समान है , state के साथ rb_protect से . इसलिए उपयोग बहुत सीधा है:

 <पी> यह एपीआई अभी तक रूबी में उपलब्ध नहीं है, और शायद कभी भी उपलब्ध नहीं होगी। आप इसे RGeo (MIT LICENSE) से ले सकते हैं।

वास्तविक दुनिया का उदाहरण

<पी> यदि आप वास्तविक दुनिया का उदाहरण देखना चाहते हैं, तो मैं आपको RGeocodebase पढ़ने के लिए प्रोत्साहित करता हूं क्योंकि हमने हाल ही में पूर्ण rb_protect पर स्विच किया है। . हमारे पास कुछ फ़ंक्शन भी हैं, जैसे rgeo_convert_to_geos_geometry , जो सरल उपयोग के लिए इस स्थिति का प्रचार करता है। यह फ़ंक्शन खोजबीन शुरू करने के लिए एक अच्छी जगह है।

<पी> हमारे द्वारा आगे चुने गए विकल्पों पर चर्चा करने के लिए बेझिझक RGeo पर एक मुद्दा खोलें।

समापन

<पी> इस पोस्ट में, हमने rb_funcall का उपयोग करने के प्रति चेतावनी दी है C के साथ क्योंकि यह मेमोरी लीक का कारण बन सकता है। हमने begin..ensure का उपयोग करके पता लगाया या rb_protect इसके बजाय.

<पी> हैप्पी कोडिंग!

<पी> पी.एस. यदि आप प्रेस से हटते ही रूबी मैजिक पोस्ट पढ़ना चाहते हैं, तो हमारे रूबी मैजिक न्यूज़लेटर की सदस्यता लें और एक भी पोस्ट न चूकें! सी एक्सटेंशन से रूबी विधियों को लागू करते समय मेमोरी लीक को रोकें

यूलिसे बुओनोमो

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

<पी> यूलिसे बुओनोमो

द्वारा सभी लेख
  1. Android में कई पंक्तियों में एक-एक करके लेआउट में प्रोग्रामेटिक रूप से बटन कैसे जोड़ें Android में कई पंक्तियों में एक-एक करके लेआउट में प्रोग्रामेटिक रूप से बटन कैसे जोड़ें

    यह उदाहरण दर्शाता है कि मैं एंड्रॉइड में एक के बाद एक कई पंक्तियों में प्रोग्रामेटिक रूप से बटन कैसे जोड़ूं। चरण 1 - एंड्रॉइड स्टूडियो में एक नया प्रोजेक्ट बनाएं, फाइल ⇒ न्यू प्रोजेक्ट पर जाएं और एक नया प्रोजेक्ट बनाने के लिए सभी आवश्यक विवरण भरें। चरण 2 - निम्न कोड को res/layout/activity_main.xml

  1. सी++ में जंप गेम IV सी++ में जंप गेम IV

    मान लीजिए कि हमारे पास arr नामक पूर्णांकों की एक सरणी है। हम शुरुआत में इंडेक्स 0 पर हैं। एक चरण में हम इंडेक्स i से i + x पर जा सकते हैं जहां:i + x =0. j जहां:arr[i] और arr[j] समान हैं और i और j समान नहीं हैं। यहाँ n सरणी का आकार है। सरणी के अंतिम सूचकांक तक पहुंचने के लिए हमें न्यूनतम चरणों की संख

  1. जावा एनम्स में महारत हासिल करना:एक व्यावहारिक मार्गदर्शिका जावा एनम्स में महारत हासिल करना:एक व्यावहारिक मार्गदर्शिका

    जावा एनम एक डेटा प्रकार है जो स्थिरांक की एक सूची संग्रहीत करता है। आप enum कीवर्ड का उपयोग करके एक enum ऑब्जेक्ट बना सकते हैं। एनम स्थिरांक घुंघराले कोष्ठकों की एक जोड़ी के भीतर अल्पविराम से अलग की गई सूची के रूप में दिखाई देते हैं। एनम, जो गणना का संक्षिप्त रूप है, एक डेटा प्रकार है जिसमें संभाव