2014-10-29 5 views
9

आप FreeAndNil प्रक्रिया संहिता पर नजर डालेंगे तो आप देखेंगे:फ्री एंडनिल कार्यान्वयन नि: शुल्क से पहले निल क्यों कर रहा है?

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

कारण वे एक वस्तु संदर्भ के लिए है और इस इसे नष्ट करने के बाद ही Nil बताए क्या है? इसके विपरीत क्यों नहीं?

+0

मैं केवल यह सुनिश्चित करने के लिए मानता हूं कि यह 'शून्य' हो जाता है भले ही 'फ्री' ने किसी प्रकार का अपवाद उठाया हो। –

+1

यदि आप स्विच करते हैं और विनाशक अपवाद उठाता है, तो आपको एक बासी पॉइंटर के साथ छोड़ दिया जाता है। Wether आपको FreeAndNil का उपयोग करना चाहिए, आप इसे यहां पढ़ सकते हैं [http://www.nickhodges.com/post/Using-FreeAndNil.aspx) और अपने स्वयं के निष्कर्ष निकालें। –

+0

अन्य संभावित धागे को इंगित करने के लिए पहले ऑब्जेक्ट मौजूद नहीं है। यदि आप आदेश को स्वैप करते हैं, नि: शुल्क और शून्य असाइनमेंट के बीच कोई अन्य थ्रेड अमान्य पॉइंटर को संदर्भित कर सकता है। – pf1957

उत्तर

10

मैं इसे इस तरह से करने के दो कारणों के बारे में सोच सकता हूं, जिनमें से कोई भी आकर्षक नहीं लगता है।

कारण 1: गारंटी नहीं है कि संदर्भ शून्य से कोई अपवाद उठाया है

कार्यान्वयन इस को प्राप्त होता है पर सेट है। यदि विनाशक उठता है, तो संदर्भ अभी भी शून्य पर सेट है। एक और तरीका है ऐसा करने के लिए एक finally ब्लॉक के साथ होगा:

try 
    TObject(Obj).Free; 
finally 
    TObject(Obj) := nil; 
end; 

इस का नकारात्मक पहलू प्रदर्शन है। विशेष रूप से x86 पर try/finally थोड़ा महंगा है। इस तरह के मौलिक दिनचर्या में इस खर्च से बचने के लिए समझदारी है।

मुझे हर कीमत पर मजबूर होने की इच्छा क्यों मिलती है? खैर, जैसे ही विनाशक विफल होने लगते हैं, आप भी हार मान सकते हैं। अब आप अपने कार्यक्रम के राज्य के बारे में स्पष्ट रूप से कारण नहीं बना सकते हैं। आप यह नहीं बता सकते कि क्या असफल रहा और आपका कार्यक्रम किस राज्य में है। यह मेरा विचार है कि एक विनाशक के चेहरे पर कार्रवाई का सही तरीका प्रक्रिया को समाप्त करना है।

कारण 2: सुनिश्चित करने के लिए अन्य सूत्र का पता लगा सकते है कि उस वस्तु को नष्ट कर दिया जा रहा है

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

तो जब तक मैं इसे एक संभावित कारण के रूप में प्रस्तुत करता हूं, मुझे विश्वास नहीं है कि एम्बरकेडरो में कोई भी वास्तव में इस तर्क से प्रभावित हुआ था।

+0

धन्यवाद। – Andrew

+0

कारण 2 को पकड़ने के लिए, 'फ्री एंड नील' स्वयं को थ्रेडसेफ होना होगा और ऐसा नहीं है इसलिए मैं वास्तव में केवल एक * (वैध) * कारण देखता हूं। –

+0

@LievenKeersmaekers मैं पहले से ही जवाब में कहता हूं। सिंक्रनाइज़ेशन के बिना सभी कोड एक अलग धागे में कर सकते हैं संदर्भ का परीक्षण किया जाएगा या नहीं। वह सुरक्षित होगा। भले ही विनाशक के पहले या बाद में शून्य के लिए असाइनमेंट मनमाने ढंग से प्रतीत होता है। व्यक्तिगत रूप से मैं वैध होने के कारण न तो कारण देखता हूं। –

9

David's second reason पर एक भिन्नता है जो थोड़ा अधिक आकर्षक है। हालांकि कोई तर्क दे सकता है कि यदि यह लागू होता है तो अन्य समस्याएं तय की जानी चाहिए।

कारण 3: एक ही धागे पर ईवेंट हैंडलर्स सुनिश्चित करने के लिए पता लगा सकते हैं कि वस्तु को नष्ट कर दिया जा रहा है

यहाँ एक ही गाढ़ा काल्पनिक उदाहरण है:

TOwner.HandleCallback; 
begin 
    if Assigned(FChild) then 
    FChild.DoSomething; 
end; 

TChildClass.Destroy; 
begin 
    if Assigned(FOnCallback) then FOnCallback; 
    inherited Destroy; 
end; 
अब

अगर Towner कॉल:

FChild.Free; 
FChild := nil; 

FChildDoSomething से इसके विनाश के बीच में पूछा जाएगा ycle। आपदा के लिए एक निश्चित नुस्खा। FreeAndNil का कार्यान्वयन अच्छी तरह से इस से बचाता है।

हाँ आप तर्क दे सकते हैं कि विनाश के दौरान गोलीबारी कॉलबैक घटनाएं खतरनाक हैं, लेकिन इसका लाभ होता है। डेल्फी/वीसीएल कोड में बहुत कम उदाहरण हैं।विशेष रूप से यदि आप कॉलिंग पॉलीमोर्फिक तरीकों को शामिल करने के लिए चिंता का दायरा बढ़ाते हैं - जो आपके नियंत्रण के बाहर विनाश अनुक्रम के पहलुओं को भी डालता है।

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

+0

+1 अच्छी तरह से समझाया गया –

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