2012-06-16 6 views
13
type 
    TSomeRecord = Record 
    field1: integer; 
    field2: string; 
    field3: boolean; 
    End; 
var 
    SomeRecord: TSomeRecord; 
    SomeRecAr: array of TSomeRecord; 

यह है कि मैं क्या है का सबसे बुनियादी उदाहरण है और के बाद से मैं पुन: उपयोग करने SomeRecord चाहते हैं (कुछ फ़ील्ड रिक्त शेष है, सब कुछ कुछ क्षेत्रों पर किया जाएगा मुक्त कराने के बिना साथ जब मैं SomeRecord पुन: उपयोग कर रहा हूँ, जो स्पष्ट रूप से अवांछित है) मैं एक ही समय में सभी क्षेत्रों को मुक्त करने का एक तरीका ढूंढ रहा हूं। मैं string[255] के साथ बाहर शुरू कर दिया और ZeroMemory() है, जो ठीक था जब तक यह स्मृति लीक शुरू कर दिया करते थे, कि क्योंकि मैं string में स्विच करने लगा पाया। मुझे अभी भी ज्ञान प्राप्त करने के लिए ज्ञान की कमी है, लेकिन ऐसा लगता है कि यह गतिशील है। मैं गतिशील सरणियों उपयोग कर रहा हूँ के रूप में अच्छी तरह से है, इसलिए मुझे लगता है कि कुछ भी गतिशील पर ZeroMemory() कोशिश कर लीक में परिणाम होगा। एक दिन बर्बाद कर बर्बाद कर दिया। मुझे लगता है मैं SomeRecord या SomeRecAr पर Finalize() का उपयोग कर ZeroMemory() से पहले द्वारा इस हल लगता है, लेकिन मुझे यकीन है कि अगर यह उचित दृष्टिकोण है या बस मुझे बेवकूफ नहीं किया जा रहा हूँ।कैसे ठीक से मुक्त रिकॉर्ड है कि एक बार में डेल्फी में विभिन्न प्रकार को रोकने के लिए?

तो सवाल यह है: कैसे सब कुछ एक ही बार में खाली करने के लिए? क्या इसके लिए कुछ एकल प्रक्रिया मौजूद है जो मुझे पता नहीं है?

एक अलग नोट पर, वैकल्पिक रूप से मैं सुझावों के लिए खुला होगा कि इन रिकॉर्ड्स को अलग-अलग तरीके से कैसे कार्यान्वित किया जाए, इसलिए मुझे सामान मुक्त करने के जटिल प्रयास करने की आवश्यकता नहीं है। मैं New() साथ रिकॉर्ड बनाने और उसके बाद हो रही यह Dispose() से छुटकारा देखा है, लेकिन मैं पता नहीं इसका क्या मतलब जब Dispose() के लिए एक कॉल के बाद एक चर, अपरिभाषित है शून्य के बजाय है। इसके अलावा, मुझे नहीं पता कि एक निश्चित प्रकार (SomeRecord: TSomeRecord) के एक चर के बीच अंतर क्या है जो एक प्रकार (SomeRecord: ^TSomeRecord) पर इंगित एक चर बनाम है। मैं इस समय उपरोक्त मुद्दों को देख रहा हूं, जब तक कोई इसे जल्दी से समझा नहीं सकता है, इसमें कुछ समय लग सकता है।

उत्तर

23

मान लें कि आप एक डेल्फी संस्करण एक रिकार्ड पर तरीकों को लागू करने का समर्थन करता है, तो आप इस तरह एक रिकार्ड स्पष्ट कर सकते हैं:

type 
    TSomeRecord = record 
    field1: integer; 
    field2: string; 
    field3: boolean; 
    procedure Clear; 
    end; 

procedure TSomeRecord.Clear; 
begin 
    Self := Default(TSomeRecord); 
end; 

अपने संकलक Default का समर्थन नहीं करता है, तो आप एक ही काफी बस की तरह कर सकते हैं इस:

procedure TSomeRecord.Clear; 
const 
    Default: TSomeRecord=(); 
begin 
    Self := Default; 
end; 

आप एक विधि में एक मान प्रकार परिवर्तनशील से बचने के लिए पसंद कर सकते हैं। जो मामले में एक समारोह है कि एक खाली रिकॉर्ड मान देता है बनाते हैं, और असाइनमेंट ऑपरेटर के साथ उपयोग करें: एक तरफ

type 
    TSomeRecord = record 
    // fields go here 
    class function Empty: TSomeRecord; static; 
    end; 

class function TSomeRecord.Empty: TSomeRecord; 
begin 
    Result := Default(TSomeRecord); 
end; 

.... 

Value := TSomeRecord.Empty; 

एक के रूप में, मैं Default(TypeIdentifier) के लिए किसी भी प्रलेखन संदर्भ नहीं मिल रहा। क्या किसी को पता है कि यह कहां पाया जा सकता है?


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

+1

@NGLN मुझे एहसास है कि इस उत्तर का सार मूल रूप से लिखा गया है। मुझे लगता है कि यह एक उत्कृष्ट जवाब था। मेरे दिमाग में यह शर्म की बात है कि आपने इसे हटा दिया। यदि आपने ऐसा उत्तर बहाल किया है तो मैं इसे हटा दूंगा और आपका वोट दूंगा। लेकिन मुझे लगता है कि इस सवाल के साथ इन सवालों के जवाब होना चाहिए। मैं चाहता था कि आप पहले थे क्योंकि आप पहले थे। –

+1

सहमत हुए। कोई कठोर भावना नहीं, मैं अब अपना रखूंगा। – NGLN

+0

@NGLN ठीक समझने के लिए धन्यवाद और मैंने अपना डाउनवोट हटा दिया है, जो कठोर था। –

5

सबसे बस समाधान मैं के बारे में सोच हो जाएगा: यहाँ कुछ कई उदाहरण पर

type 
    PSomeRecord = ^TSomeRecord; 
    TSomeRecord = record 
    Field1: Integer; 
    Field2: String; 
    Field3: Boolean; 
    end; 
    TSomeRecords = array of TSomeRecord; 
    PSomeRecordList = ^TSomeRecordList; 
    TSomeRecordList = array[0..MaxListSize] of TSomeRecord;  
const 
    EmptySomeRecord: TSomeRecord =(); 
    Count = 10;  
var 
    SomeRecord: TSomeRecord; 
    SomeRecords: TSomeRecords; 
    I: Integer; 
    P: PSomeRecord; 
    List: PSomeRecordList; 

procedure ClearSomeRecord(var ASomeRecord: TSomeRecord); 
begin 
    ASomeRecord.Field1 := 0; 
    ASomeRecord.Field2 := ''; 
    ASomeRecord.Field3 := False; 
end; 

function NewSomeRecord: PSomeRecord; 
begin 
    New(Result); 
    Result^.Field1 := 0; 
    Result^.Field2 := ''; 
    Result^.Field3 := False; 
end; 

और फिर:

const 
    EmptySomeRecord: TSomeRecord =(); 
begin 
    SomeRecord := EmptySomeRecord; 

लेकिन अपने प्रश्न के सभी शेष भागों को संबोधित करने, इन परिभाषाओं ले उन पर कैसे काम करें:

begin 
    // Clearing a typed variable (1): 
    SomeRecord := EmptySomeRecord; 

    // Clearing a typed variable (2): 
    ClearSomeRecord(SomeRecord); 

    // Initializing and clearing a typed array variabele: 
    SetLength(SomeRecords, Count); 

    // Creating a pointer variable: 
    New(P); 

    // Clearing a pointer variable: 
    P^.Field1 := 0; 
    P^.Field2 := ''; 
    P^.Field3 := False; 

    // Creating and clearing a pointer variable: 
    P := NewSomeRecord; 

    // Releasing a pointer variable: 
    Dispose(P); 

    // Creating a pointer array variable: 
    ReallocMem(List, Count * SizeOf(TSomeRecord)); 

    // Clearing a pointer array variable: 
    for I := 0 to Count - 1 do 
    begin 
    Pointer(List^[I].Field2) := nil; 
    List^[I].Field1 := 0; 
    List^[I].Field2 := ''; 
    List^[I].Field3 := False; 
    end; 

    // Releasing a pointer array variable: 
    Finalize(List^[0], Count); 

चुनें और/या आपको पसंद करें।

+0

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

+4

निरंतर की एक और लचीली परिभाषा 'खाली SomeRecord: TSomeRecord =();' और कंपाइलर को शून्य में भरने दें। –

+0

@ डेविड: धन्यवाद! – NGLN

1

SomeRecord: TSomeRecord, SomeRecordTSomeRecord प्रकार का एक उदाहरण/चर होगा। SomeRecord: ^TSomeRecord, SomeRecordTSomeRecord के उदाहरण या चर के लिए एक सूचक होगा। अंतिम मामले में, SomeRecord एक टाइप किया गया पॉइंटर होगा। यदि आपका एप्लिकेशन दिनचर्या के बीच बहुत अधिक डेटा स्थानांतरित करता है या बाहरी एपीआई के साथ बातचीत करता है, तो टाइप किए गए पॉइंटर की सिफारिश की जाती है।

new() और dispose() केवल टाइप किए गए पॉइंटर्स के साथ उपयोग किए जाते हैं। टाइप किए गए पॉइंटर्स के साथ कंपाइलर में इस प्रकार के वर्रों के साथ आपके एप्लिकेशन का उपयोग करने वाली मेमोरी का नियंत्रण/पता नहीं है। टाइप किए गए पॉइंटर्स द्वारा उपयोग की जाने वाली मेमोरी को मुक्त करने के लिए आप पर निर्भर है।

दूसरी तरफ, जब आप उपयोग और घोषणा के आधार पर सामान्य चर का उपयोग करते हैं, तो संकलक उनके द्वारा उपयोग की जाने वाली मेमोरी को मुक्त कर देगा जब यह मानता है कि वे अब आवश्यक नहीं हैं। उदाहरण के लिए:

function SomeStaff(); 
var 
    NativeVariable: TSomeRecord; 
    TypedPointer: ^TSomeRecord; 
begin 
    NaviveVariable.Field1 := 'Hello World'; 

    // With typed pointers, we need to manually 
    // create the variable before we can use it. 
    new(TypedPointer); 
    TypedPointer^.Field1 := 'Hello Word'; 

    // Do your stuff here ... 

    // ... at end, we need to manually "free" 
    // the typed pointer variable. Field1 within 
    // TSomerecord is also released 
    Dispose(TypedPointer); 

    // You don't need to do the above for NativeVariable 
    // as the compiler will free it after this function 
    // ends. This apply also for native arrays of TSomeRecord. 
end; 

उपरोक्त उदाहरण में, चर NativeVariable केवल SomeStaff समारोह के भीतर प्रयोग किया जाता है, तो संकलक स्वचालित रूप से मुक्त यह समारोह समाप्त होता है जब। एरे और रिकॉर्ड्स "फ़ील्ड्स" सहित लगभग सबसे देशी चर के लिए यह ऐप। ऑब्जेक्ट्स का अलग-अलग व्यवहार किया जाता है, लेकिन यह एक और पोस्ट के लिए है।

6

मत सोचो मत समझो!

"डिफ़ॉल्ट" record असाइन करना केवल सीपीयू पावर और मेमोरी का नुकसान है।

जब recordTClass के भीतर घोषित किया गया है, तो यह शून्य से भरा हुआ है, इसलिए प्रारंभ किया गया। जब इसे स्टैक पर आवंटित किया जाता है, केवल संदर्भ गणना किए गए चर प्रारंभ होते हैं: अन्य प्रकार के चर (जैसे पूर्णांक या डबल या बूलियन या अंकन) एक यादृच्छिक स्थिति (शायद शून्य नहीं) में होते हैं। जब इसे ढेर पर आवंटित किया जाएगा, getmem कुछ भी शुरू नहीं करेगा, allocmem शून्य से सभी सामग्री भर देगा, और new केवल संदर्भ-गिनती सदस्यों (जैसे स्टैक प्रारंभिकरण पर) प्रारंभ करेगा: सभी मामलों में, आपको dispose का उपयोग करना चाहिए, या तो finalize+freemem एक ढेर-आवंटित record जारी करने के लिए। उपयोग के बाद एक रिकार्ड सामग्री पुनर्स्थापित करने के लिए (या "zeromemory"), कभी नहीं का उपयोग करें "fillchar" बिना पिछले एक "finalize":

तो आपके प्रश्न के सटीक, अपनी खुद की धारणा सही था। यहां सही और तेज़ तरीका है:

Finalize(aRecord); 
FillChar(aRecord,sizeof(aRecord),0); 

एक बार फिर, यह एक डिफ़ॉल्ट रिकॉर्ड असाइन करने से तेज़ होगा। और सभी मामलों में, यदि आप Finalize का उपयोग करते हैं, यहां तक ​​कि कई बार, यह किसी भी स्मृति को रिसाव नहीं करेगा - 100% धन वापस वारंटी!

संपादित करें:aRecord := default(TRecordType) द्वारा बनाया गया कोड को देखने के बाद, कोड अच्छी तरह से अनुकूलित है: यह वास्तव में एक Finalize + stosd का गुच्छा FillChar अनुकरण करने के लिए। तो अगर वाक्यविन्यास एक प्रति/असाइनमेंट (:=) है, तो इसे प्रतिलिपि/असाइनमेंट के रूप में लागू नहीं किया गया है। मेरी गलती यहाँ

लेकिन मैं अभी भी तथ्य यह है कि एक :=, प्रयोग की जाने वाली जहां Embarcadero बेहतर होना चाहिए aRecord.Clear वाक्य रचना के रूप में की तरह एक record विधि का इस्तेमाल किया, बस DelphiWebScript's dynamic arrays की तरह है पसंद नहीं है। वास्तव में, यह := सिंटैक्स सी # द्वारा उपयोग किया जाता है। लगता है जैसे एम्बकार्डरो बस this is weird को खोजने के बिना, हर जगह सी # वाक्यविन्यास की नकल करता है। क्या बात है यदि डेल्फी सिर्फ अनुयायी है, और लागू नहीं होता "इसका तरीका" सोचता है? लोग हमेशा अपने पूर्वजों को मूल सी # पसंद करेंगे (डेल्फी के पास एक ही पिता है)।

+0

बिना किसी टिप्पणी के इतने गर्व "-1" क्यों? ;) –

+0

आपका डाउन-वोटर स्पष्ट रूप से उनके दिमाग को बदल देता है, लेकिन यहां एक डाउनवॉट योग्य होगा। सबसे पहले, प्रदर्शन शायद ओपी के लिए सबसे महत्वपूर्ण कारक नहीं है। लेकिन सबसे महत्वपूर्ण बात यह है कि यहां आपके दावे सही नहीं हैं। 'aRecord: = डिफ़ॉल्ट (TSomeRecord)' कुशल है। –

+0

@ डेविड हेफरन बेशक, यह धीमा नहीं है। लेकिन निश्चित रूप से अंतिम रूप देना + प्रतिलिपि + फिलर को अंतिम रूप देने से धीमा हो जाएगा। और एक असाइनमेंट सिर्फ भ्रमित है। अपने उत्तर में मेरी टिप्पणी देखें। प्रतिलिपि रिकॉर्ड डेल्फी में अनुकूलित से बहुत दूर है: यह आरटीटीआई का उपयोग करता है, और संकलक अनुकूलित कोड नहीं - देखें http://blog.synopse.info/post/2010/03/23/CopyRecord-faster-proposal –

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

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