2010-07-01 14 views
42

फ्री और फ्री एंड नील के बीच बुनियादी अंतर क्या है?जो बेहतर है: नि: शुल्क या नि: शुल्क और नील?

फ्री एंड नील = फ्री + नील है?

मुझे नि: शुल्क उपयोग कब करना चाहिए और मुझे फ्री एंडनल का उपयोग कब करना चाहिए?

मुझे यह नहीं मिल रहा है जब कोई मेरी मदद कर सकता है।

अग्रिम धन्यवाद।

+1

यहां एक विस्तारित चर्चा: https://forums.embarcadero.com/thread.jspa?threadID=33112 –

+0

@ थ्रेड को कई अन्य लोगों की तरह थ्रेड करें, – mjn

+1

नई चर्चाएं गैर-तकनीक [यहां] पर हैं (https: //forums.embarcadero.com/thread.jspa?threadID=65321&tstart=15) और [यहां] (https://forums.embarcadero.com/thread.jspa?threadID=63906&tstart=0) – mjn

उत्तर

42

,

procedure TForm1.FormCreate(Sender: TObject); 
var 
    bm: TBitmap; 
begin 
    bm := TBitmap.Create; 
    bm.LoadFromFile('C:\Users\Andreas Rejbrand\Documents\RAD Studio\6.0\Demos\DelphiWin32\VCLWin32\Football\up.bmp'); 
    bm.Free; 

    if Assigned(bm) then 
    bm.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\test.bmp') 
    else 
    ShowMessage('Cannot save! The bitmap does no longer exist!'); 
end; 

यह मेरा डेस्कटॉप पर एक त्रुटि या गलत (खाली) बिटमैप पैदा करेगा:

procedure FreeAndNil(var Obj); 
var 
    Temp: TObject; 
begin 
    Temp := TObject(Obj); 
    Pointer(Obj) := nil; 
    Temp.Free; 
end; 

उदाहरण

निम्नलिखित कोड पर विचार करें:

और कार्यान्वयन पर एक नजर है क्योंकि मैं एक वस्तु का उपयोग करने की कोशिश करता हूं जिसे मुक्त किया गया है। हां, भले ही bm को मुक्त कर दिया गया हो, फिर भी यह "असाइन किया गया" है, यानी bm अभी भी एक मेमोरी एड्रेस को इंगित करता है, भले ही वहां कुछ भी नहीं है (उपयोग करने योग्य)। इसे दूर करने के लिए, कोई एक सुरक्षा के रूप में bm := nil सेट कर सकता है, फिर assigned(bm) झूठी वापसी करेगा, जैसा कि कोई चाहता है। अधिक या कम, FreeAndNil(bm)bm.Free; bm := nil के लिए एक शॉर्टेंड है। पहला कथन ऑब्जेक्ट द्वारा उपयोग की जाने वाली सभी मेमोरी (और ओएस संसाधन, सीपीयू टाइम इत्यादि) को मुक्त करता है, और bm := nil "पॉइंटर" bm से nil पर सेट करता है, ताकि bm उस स्थान पर इंगित न हो जहां ऑब्जेक्ट होता था, लेकिन नहीं लंबा है इस तरह आप (और assigned जैसे दिनचर्या) विश्वास करने के लिए मूर्ख नहीं होंगे कि अभी भी एक बिटमैप ऑब्जेक्ट है।

चर्चा

कुछ लोग कहते हैं कि आप हमेशा FreeAndNil(foo) बजाय foo.Free उपयोग करना चाहिए। जरूर क्यों नहीं? अतिरिक्त निर्देश foo := nil शायद निष्पादित करने के लिए बहुत से नैनोसेकंड नहीं लेगा, और वास्तव में assigned(foo) = false एक मुक्त वस्तु की एक बहुत अच्छी संपत्ति है। लेकिन फिर, यदि आप जानते हैं कि आप क्या कर रहे हैं, और जानते हैं कि आप इसे मुक्त करने के बाद कभी भी foo ऑब्जेक्ट का उपयोग नहीं करेंगे, तो आप केवल foo.free पर रह सकते हैं। असल में, कुछ तर्क देंगे कि कई मामलों में (लेकिन सभी नहीं), एक मुक्त वस्तु के चर का उपयोग करने की कोशिश कर एक बग है। (बेशक ऐसे मामले हैं जहां यह जानबूझकर कर रहे हैं - आप एक वस्तु foo है कि कभी कभी सौंपा है और कभी कभी किया जाता है नहीं है।)

+4

"कुछ तर्क देंगे कि कई मामलों में (लेकिन सभी नहीं), मुक्त किए गए किसी ऑब्जेक्ट का उपयोग करने का प्रयास करना एक बग है" - यह हमेशा एक बग है, न कि कभी-कभी "। वेरिएबल्स और ऑब्जेक्ट्स अलग-अलग जानवर हैं: कई बार कई बार "शून्य" असाइन किया जा सकता है, लेकिन यह एक शून्य वस्तु नहीं है, केवल एक असाइन किए गए चर है। –

+0

@ कोसमिन प्रंड: बेशक। मैं इसे बदल दूंगा। –

+0

@Cosmin - बिल्कुल सही नहीं है। असाइन किए गए वेरिएबल्स एनआईएल होने की संभावना नहीं है जब तक कि वे तार या इंटरफ़ेस संदर्भ न हों। दूसरी तरफ असाइन किए गए वर्ग के सदस्य एनआईएल होने के लिए निश्चित हैं जब तक कि आप जानबूझकर न्यूइंस्टेंस कार्यान्वयन को ओवरराइड नहीं करते। – Deltics

6

@Bharat, Free और FreeAndNil के बीच अंतर यह है कि मुक्त स्मृति के अलावा एक के द्वारा प्रयोग किया है ऑब्जेक्ट FreeAndNil ऑब्जेक्ट संदर्भ शून्य को सेट करता है।

आप जाँच कर सकते हैं शोध करे या FreeAndNil

17
मूल रूप से

के बारे में उपयोग नि: शुल्क विचार विमर्श के लिए लिंक, FreeAndNil के संदर्भ सेट शून्य और फिर ऑब्जेक्ट को मुक्त करता है। यह इसे असाइन किए गए के रूप में चिह्नित करता है। इसलिए फ्री एंड नील का उपयोग करने के लिए आपको एकमात्र कारण यह है कि यदि आपका कोड संदर्भ का पुन: उपयोग करने जा रहा है। यदि आप एक विनाशक में हैं या अंततः ब्लॉक, उन वस्तुओं को मुक्त करना जिन्हें आप कभी भी स्पर्श नहीं करेंगे, बस नि: शुल्क उपयोग करें।

Delphi Memory Management Made Simple देखें जब मुझे यह उपयोगी लगता था। नीचे मागी की टिप्पणी भी पढ़ने लायक है।

+4

असल में, यह संदर्भ को स्थानीय var में संदर्भित करता है, संदर्भ को शून्य करता है और फिर स्थानीय var का उपयोग करके ऑब्जेक्ट को मुक्त करता है। FreeAndNil को NilAndFree नाम दिया जाना चाहिए था :) :) –

+0

हाँ। अधूरे विनाशक और फ्री एंड एनआईएल() अच्छे बेडफेलो नहीं हैं। – Deltics

+1

@ मारजन, मैंने हाल ही में एक मामला दर्ज किया था, जहां नामकरण ने शायद मुझे एक जटिल जटिल सिंगलटन कार्यान्वयन में एक बग की पहचान करने में कुछ समय बचाया होगा जिसमें एक विनाशक से वर्ग चर का उपयोग करना शामिल था जो पहले 'फ्री एंड नील' था ...;) –

8

मैं एक अलग तरीके से जवाब दूंगा।

शायद, ऑब्जेक्ट को मुक्त करने के बाद nil के साथ अपना ऑब्जेक्ट संदर्भ भरना हमेशा एक अच्छा विचार नहीं है।

इस तरह, आपके पास उस संदर्भ के बीच भेद नहीं है जिसका उपयोग कभी नहीं किया गया था (और इसलिए nil), और एक संदर्भ जिसका उपयोग किया गया है, लेकिन भविष्य में इसका उपयोग नहीं किया जाना चाहिए।

तो, इसे एक जादू संख्या के साथ भरना (FastMM मेमोरी मैनेजर स्मृति के ब्लॉक की सामग्री के साथ कर सकता है जब उन ब्लॉक को मुक्त किया जाता है)।

--jeroen

2

यहां तक ​​कि अगर नि: शुल्क की तुलना में बहुत अलग हो प्रतीत नहीं होता है, तो यह आपको एक बहुत बाद में, जबकि कीड़े के लिए अपने कोड शिकार में मदद मिलेगी।

बस सोचें कि क्या होता है यदि आप फ्री एंड नील का उपयोग नहीं करते हैं और फिर कहीं भी आपके कोड में आप एक मुक्त वस्तु तक पहुंचते हैं। यदि आप भयानक भाग्यशाली हैं, तो आपका प्रोग्राम क्रैश हो जाएगा जब यह घर चलाता है (हाँ यह दुर्घटना एक 'अच्छा' दुर्घटना है)। यदि आप थोड़ा दुर्भाग्यपूर्ण हैं तो यह ग्राहक के कंप्यूटर में दुर्घटनाग्रस्त हो जाएगा। फिर असली दर्द शुरू होता है!

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

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

कुछ रूढ़िवादी लोग कह सकते हैं कि यह सरल कॉल रैम और सीपीयू संसाधनों को बर्बाद कर देगा। मैं कभी भी कभी नहीं कहूंगा कि स्मृति/सीपीयू को संरक्षित करना बुरा है। मैं छोटे/तेज़/मोनोलिथिक अनुप्रयोगों को भी वितरित करना चाहता हूं!लेकिन मुझे नहीं लगता कि FreeAndNil का उपयोग करने से हटाने से कुछ बाइट्स और सीपीयू चक्र (सचमुच कुछ) बर्बाद हो जाएंगे। यह दिन-दर-दिन जीवन में एक वास्तविक अंतर नहीं करेगा, खासकर जब आपको लगता है कि एक ग्राफिक संसाधन जैसे टीबटन ग्लिफ़ या आपके प्रोग्राम का आइकन 50-300 केबी ले सकता है, और आपके प्रोग्राम में इनमें से कई दर्जन हो सकते हैं। http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple

विपक्ष
एलन Bauer यहाँ कैसे उपयोग करने के बारे एक उदाहरण दिखाता है:

पेशेवरों
मेसन व्हीलर पहले से ही एक लेख है कि 'आलसी रचना' विधि FreeAndNil का उपयोग करता है कि हम सब एक दिन में प्रयोग किया जाता से पता चलता को इंगित करता है एक निश्चित मामले (एक दृश्य घटक के विनाशक) में फ्री एंड नील और वास्तव में खराब: http://blogs.embarcadero.com/abauer/2010/02/16/38916
एलन बताता है कि फ्री एंड नील को बेहतर तरीके से बदला जाना चाहिए। उदाहरण के लिए फास्टएमएम के साथ। हालांकि, यहां एक आसान कोड है जहां फास्टएमएम विफल रहता है जबकि फ्री एंड नील दिन बचाता है: http://codeverge.com/embarcadero.delphi.rtl/freeandnil-to-use-or-not-to-use/1067733

चूंकि प्रो और फ्री एंड नील के खिलाफ दोनों तर्क हैं, तो यह तय करना आपके लिए है कि यह पसंद है या नहीं।

+2

-1। "हमेशा" गलत है। यदि आपके पास किसी विधि में स्थानीय चर है, तो FreeAndNil का उपयोग करने की बहुत कम या आवश्यकता नहीं है, क्योंकि var केवल स्थानीय दायरे में ही पहुंच योग्य है। यदि आप ** ** ** नहीं देख सकते हैं कि आपको फ्री एंड नील की आवश्यकता नहीं है, तो आपको उस विधि में लाइनों की संख्या को कम करने के लिए अपने कोड को दोबारा करने की आवश्यकता है। कभी भी ऐसा उत्तर देने का एक बुरा विचार है जो "हमेशा" कहता है जब तक आप पूरी तरह साबित नहीं कर सकते कि उस नियम में कोई अपवाद नहीं है। –

+0

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

+0

यदि आप यह नहीं कह सकते हैं * कभी भी स्थानीय रूप से किसी स्थानीय को अपग्रेड नहीं करते हैं, और आपका पूर्णकालिक नौकरी कोड लिख रहा है, तो आपको कीबोर्ड से सावधानीपूर्वक कदम उठाना चाहिए और एक नई नौकरी मिलनी चाहिए। मैं ईमानदारी से कह सकता हूं कि पिछले दशक में मैंने कभी भी एक स्थानीय वैरिएबल को गलती से अपग्रेड नहीं किया है और उस विधि में कोई समस्या है जो उस स्थानीय चर का उपयोग करती है जहां उचित समाधान फ्री एंड नील होगा। मेरे पास कोड के 5 मिलियन से अधिक लाइनों के साथ कई उत्पादन अनुप्रयोग हैं, और स्रोत के एक grep को अपने कोड में FreeAndNil के दो उदाहरण मिलते हैं। –

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