2012-03-03 12 views
7

प्रसंग 1डेल्फी गुजर मानकों/कॉपी

var text:String; 

text:='hello'; 

myFunc(text); 

Context2

function myFunc(mytext:String); 
var textcopy:String; 
begin 

    textcopy:=mytext; 

end; 

Context2 पर myFunc Context1, स्थानीय चर mytext से बुलाया गया था बाहर एक स्मृति की ओर इशारा करते है संदर्भ 2? या mytext के पास अपनी क्षमता मेमोरी स्पेस है और text की समान सामग्री से भरा/कॉपी किया गया है? मुझे शायद कुछ मूलभूत याद आ रही है, क्योंकि मुझे access violation त्रुटि मिल रही है।

स्पष्ट रूप से निर्दिष्ट करने का कोई तरीका है कि किसी फ़ंक्शन को संदर्भ या मान द्वारा पैरामीटर प्राप्त करना चाहिए, तो सी में कॉपी करना चाहिए? मुझे यकीन नहीं है कि मैं इसे कैसे कर रहा हूं।

+0

आम तौर पर, इसका परिणाम एवी में नहीं होना चाहिए! मुझे संदेह है कि ये कोड अलग डीएलएल से चल रहे हैं? तब 'ShareMem' का उपयोग करें। – NGLN

+0

और 'पहुंच उल्लंघन की कुछ त्रुटि' है? – RBA

+0

@NGLN हाँ मैं सी ++ में लिखे गए एक डीएल का उपयोग कर रहा हूं इसलिए मैंने एक पैस हेडर फ़ाइल लिखा था। और मैं परिस्थितियों में एवी प्राप्त कर रहा हूं कि मुझे यह पता नहीं लगाया जा सकता है कि शायद यह गुजरने वाला संदर्भ क्यों नहीं है और कॉपी नहीं कर रहा है जब मैं पॉइंटर्स के साथ काम करता हूं। –

उत्तर

20

डेल्फी तारों के लिए मेमोरी प्रबंधन थोड़ा असामान्य है। myFunc(text) पर कॉल करने के बाद, और textcopy := mytext असाइन करें, सभी तीन चर (text, mytext और textcopy) मूल स्ट्रिंग के समान पते पर इंगित करेंगे।

लेकिन जैसे ही आप इन चरों से एक का उपयोग के रूप में स्ट्रिंग के लिए परिवर्तन करने के लिए, डेल्फी क्लोन पर्दे के पीछे स्ट्रिंग, और अपने परिवर्तनों की नकल करने के लिए लागू कर रहे हैं। अन्य दो चर अभी भी मूल को इंगित करते हैं, इसलिए वे अपरिवर्तित रहते हैं। तो संदर्भ 2 में किए गए कोई भी परिवर्तन संदर्भ 1 में नहीं देखे जाएंगे - यह "प्रतिलिपि लिखने" मैकेनिक प्रभावी ढंग से आपको पास-बाय-वैल्यू अर्थशास्त्र देता है। इन सभी तारों को संदर्भ-गिना जाता है, और सभी संदर्भ दायरे से बाहर होने के बाद स्वचालित रूप से मुक्त हो जाएंगे।

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

यदि आप संदर्भ पास करना चाहते हैं, तो अपने कार्य को myFunc(var mytext: String) के रूप में घोषित करें। यदि आप स्ट्रिंग की प्रतिलिपि बनाने के लिए डेल्फी को मजबूर करना चाहते हैं, तो इसे संशोधित होने तक प्रतीक्षा करने के बजाय, आप System.UniqueString का उपयोग कर सकते हैं।

+1

संदर्भित है यह सच है लेकिन यह पूरी शुरुआत के लिए वास्तव में सहायक नहीं है। लिखने वाले जादू पर सभी प्रतियों के बारे में बिंदु यह है कि यह एक संदर्भ प्रकार को मान प्रकार की तरह व्यवहार करता है। मुझे डर है कि यह जवाब, यद्यपि यह सही है, केवल पहले से ही बहुत भ्रमित नौसिखिया को भ्रमित कर देगा। –

+1

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

+0

अधिक बेहतर उत्तर संपादित करें। एवी असंबंधित है। अन्य प्रश्न देखें। –

6

डेल्फी में संदर्भ द्वारा पारित करने के लिए आप स्पष्ट रूप से वर कीवर्ड जोड़ने:

procedure myFunc(var mytext:String); 

इसका मतलब है कि myFunc स्ट्रिंग की सामग्री को संशोधित और फोन करने वाले परिवर्तनों को देखने के कर सकते हैं।

+0

मेरे उदाहरण में 'टेक्स्ट' और' mytext' प्रत्येक ने आवंटित स्मृति को अलग किया है, है ना? –

+0

@Vitimtk - नहीं, 'text' और 'mytext' एक ही मेमोरी – kludg

9

डेल्फी में, स्ट्रिंग एक संदर्भ प्रकार है जो आमतौर पर मान प्रकार की तरह कार्य करता है। इसे ढेर पर आवंटित किया जाता है (अधिकांश मूल्य प्रकारों की तरह ढेर नहीं) और इसमें स्वचालित संदर्भ गिनती और कॉपी-ऑन-राइट सेमेन्टिक्स शामिल हैं।

यह समझने के लिए कि इसका क्या अर्थ है, सामान्य मान प्रकारों, उदाहरण के लिए एक पूर्णांक, व्यवहार करते हैं जब एक प्रक्रिया के लिए एक पैरामीटर के रूप में पारित: PassByReferenceInOut में

var 
    gValue: Integer; 

procedure PassByValue(aValue: Integer); 
begin 
    // Here @gValue <> @aValue 
    aValue := aValue + 2; 
    // Here @gValue <> @aValue 
end; 

procedure PassByRefrenceInOut(var aValue: Integer); 
begin 
    // Here @gValue = @aValue 
    aValue := aValue + 2; 
    // Here @gValue = @aValue 
end; 

procedure CallProcedures; 
begin 
    gValue := 0; 
    PassByValue(gValue); 
    // gValue is still 0 
    PassByReferenceInOut(gValue); 
    // gValue is 2 
end; 

वर पैरामीटर तर्क के सूचक के पास करने का सी सम्मेलन के बराबर है।

एक ही अर्थ विज्ञान स्ट्रिंग पैरामीटर गुजर पर लागू होते हैं, लेकिन वहाँ मूल्यों की आंतरिक प्रतिनिधित्व में एक सूक्ष्म अंतर है:

var 
    gValue: string; 

procedure PassByValue(aValue: string); 
begin 
    // Here PChar(gValue) = PChar(aValue) <<<< 
    aValue := aValue + '2'; 
    // Here PChar(gValue) <> PChar(aValue) 
end; 

procedure PassByRefrenceInOut(var aValue: string); 
begin 
    // Here PChar(gValue) = PChar(aValue) 
    aValue := aValue + '2'; 
    // Here PChar(gValue) = PChar(aValue) 
end; 

procedure CallProcedures; 
begin 
    gValue := ''; 
    PassByValue(gValue); 
    // gValue is still '' 
    PassByReferenceInOut(gValue); 
    // gValue is '2' 
end; 

क्या आप वाकई एक प्रक्रिया स्ट्रिंग की अपनी एक प्रतिलिपि पर चल रही है बनाना चाहते हैं मान, अद्वितीय स्ट्रिंग प्रक्रिया का उपयोग करें, उदाहरण के लिए:

procedure PassByValue(aValue: string); 
begin 
    // Here PChar(gValue) = PChar(aValue) 
    UniqueString(aValue); 
    // Here PChar(gValue) <> PChar(aValue) 
    aValue := aValue + '2'; 
    // Here PChar(gValue) <> PChar(aValue) 
end; 
+2

पहले एक साधारण डेटा प्रकार पर व्यवहार को समझाना अच्छा होता है। – martinstoeckli

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