2016-06-19 11 views
5

मैं इस कोड है (मैं TStringList के लिए स्ट्रिंग वस्तु जोड़ने की जरूरत है):क्या मुझे SysAllocString के साथ आवंटित एक BSTR (वाइडस्ट्रिंग) मुक्त करना होगा?

var 
    WS: WideString; 
begin 
    WS := 'allocated string'; 
    SL.AddObject('my string', TObject(SysAllocString(PWideChar(WS)))); 

और बाद में इसे पढ़ा:

var 
    WS: WideString; 
begin 
    WS := PWideChar(SL.Objects[0]); 
    ShowMessage(WS); 

मैं अगर प्रणाली BSTR जो था का ख्याल रखेंगे सोच रहा था SysAllocString के साथ आवंटित। या मुझे SysFreeString पर कॉल करना चाहिए? यह दस्तावेज से स्पष्ट नहीं है।

अब, यदि सिस्टम इसे आवंटित करता है, तो क्या यह साबित करने का कोई तरीका है?

पी.एस: दरअसल, इसे कहते हैं suffucient है:

SL.AddObject('my string', TObject(PWideChar(WS))); 

SysAllocString का उपयोग कर के बिना। (और मुझे समझ में नहीं आता कि यह कैसे काम करता है)

उत्तर

6

यहां निम्न पंक्ति BSTR आवंटित करती है और इसके सूचक को SL.Objects[] सूचक में भरती है।

var 
    WS: WideString; 
begin 
    WS := PWideChar(SL.Objects[0]); 

यहाँ एक नई WS उदाहरण आवंटित किया जाएगा, तो आपके BSTR उदाहरण SL.Objects[0] द्वारा बताया जारी नहीं किया जाएगा:

SL.AddObject('my string', TObject(SysAllocString(PWideChar(WS)))); 

तो निम्नलिखित निश्चित स्मृति रिसाव हो जाएगा।

और निम्नलिखित संयोग से काम कर रहा है:

SL.AddObject('my string', TObject(PWideChar(WS))); 

स्मृति PWideChar(WS) स्मृति बफर द्वारा बताया अभी भी पिछले WS: WideString उदाहरण के लिए युक्त है। तो यह काम कर सकता है ... जब तक बफर का पुन: उपयोग नहीं किया जाता है और किसी अन्य डेटा द्वारा ओवरराइड किया जाता है, और एक और पाठ वापस आ जाता है, या एक यादृच्छिक जीपीएफ होता है।

सलाह द्वारा: डेल्फी प्रकार प्रणाली को धोखा कभी नहीं ... एक चर TObject के रूप में आपके द्वारा लिखा गया में एक TObject से कुछ और भंडारण, जब तक आप जानते हैं कि आप क्या कर रहे हैं। पॉइंटर्स के साथ तब तक न खेलें जब तक कि आप नहीं जानते कि वे क्या हैं और वे कैसे काम करते हैं।

मुझे WideString को TStrings.Object[] प्रविष्टि के भीतर संग्रहीत करने का कोई लाभ नहीं दिख रहा है!अपनी डेटा संरचना बदलें: अपनी स्ट्रिंग को संग्रहीत करने के लिए एक सच्चे class बनाएं। फिर सब कुछ स्पष्ट और साफ होगा:

type 
    TMyStoreWS = class 
    protected 
    fText: WideString; 
    public 
    constructor Create(const aText: WideString); virtual; 
    property Text: WideString read fText write fText; 
    end; 

constructor TMyStoreWS.Create(const aText: WideString); 
begin 
    inherited Create; 
    fText := aText; 
end; 

... 
SL.AddObject('my string', TMyStoreWS.Create(aText)); // clean 
... 
ShowMessage(SL.Objects[0].Text); // clean 
SL.Objects[0].Free; // don't forget to release 

एक class उदाहरण के आवंटन के छोटे भूमि के ऊपर एक BSTR स्ट्रिंग आवंटन के संबंध में negligeable है, मैं आपको बता सकता। और आपका कोड निश्चित रूप से बनाए रखने/विकसित करने के लिए क्लीनर और आसान होगा।

+0

मैं सिस्टम को वाइडस्ट्रिंग "ऑब्जेक्ट" के विनाश को प्रबंधित करने की उम्मीद कर रहा था। यदि मैं कक्षा संरचना का उपयोग करता हूं तो मुझे प्रत्येक ऑब्जेक्ट को मैन्युअल रूप से मुक्त करने की आवश्यकता होती है (TStringList के लिए D7 में कोई स्वामित्व नहीं है)। मुझे अभी भी यकीन नहीं है कि मुझे ** ** ** स्ट्रिंग्स को मुक्त करना होगा जो 'SysAllocString' के साथ आवंटित किए गए हैं या सिस्टम मेरे लिए इसका ख्याल रख सकता है? ... – zig

+0

हां, आपको ** ** आवंटित मुक्त BSTR स्ट्रिंग्स SysAllocString। –

2

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

यह बुरा है क्योंकि अब आपके पास एक लापरवाह पॉइंटर है। यही कारण है कि आपको SysAllocString की आवश्यकता है।

SysAllocString क्या आपके द्वारा फ़ीड की जाने वाली स्ट्रिंग की एक प्रति बना देता है। यह प्रति प्रबंधित नहीं होती है, इसलिए आपको SysFreeString का उपयोग करके इसे स्वयं नष्ट करना होगा।

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