2009-11-09 21 views
10

सी # में, एक संरचना (या कक्षा) घोषित करना संभव है जिसमें पॉइंटर प्रकार का सदस्य है, जैसे:सी #: सूचक प्रकार के रूप में सूचक प्रकार का उपयोग?

unsafe struct Node 
{ 
    public Node* NextNode; 
} 

क्या यह कभी सुरक्षित है (गलती .. एक पल के लिए अनदेखा करें जो विडंबनात्मक छोटा unsafe ध्वज ..) इस निर्माण का उपयोग करने के लिए? मेरा मतलब ढेर पर लंबे समय तक भंडारण के लिए है। जो मैं समझता हूं, जीसी चीजों को चारों ओर स्थानांतरित करने के लिए स्वतंत्र है, और जब यह स्थानांतरित किए गए किसी भी संदर्भ के संदर्भ को अपडेट करता है, तो क्या यह पॉइंटर्स भी अपडेट करता है? मैं अनुमान लगा रहा हूं, जो इस निर्माण को बहुत असुरक्षित बना देगा, है ना?

मुझे यकीन है कि ऐसा करने के लिए बेहतर विकल्प हैं, लेकिन इसे morbid जिज्ञासा कहते हैं।

संपादित करें: कुछ भ्रम प्रतीत होता है। मुझे पता है कि यह एक महान निर्माण नहीं है, मैं पूरी तरह से जानना चाहता हूं कि यह हमेशा एक सुरक्षित निर्माण है, यानी: क्या पॉइंटर को जो भी आपने मूल रूप से इंगित किया है उसे इंगित करने की गारंटी दी है?

मूल सी-कोड का उपयोग बिना किसी पेड़ (गहराई पहले) को घुमाने के लिए किया जाता था, जहां पेड़ को सरणी में संग्रहीत किया जाता है। तब सरणी को पॉइंटर बढ़ाने से गुजरता है, जब तक कोई निश्चित स्थिति पूरी नहीं हो जाती है, तो पॉइंटर को नेक्स्ट नोड पर सेट किया जाता है, जहां ट्रैवर्सल जारी रहता है। बेशक, सी # में पूरा किया जा सकता है:

struct Node 
{ 
    public int NextNode; 
    ... // other fields 
} 

जहां int अगले नोड की सरणी में अनुक्रमणिका है। लेकिन प्रदर्शन कारणों से, मैं सीमाओं से बचने के लिए पॉइंटर्स और fixed सरणी के साथ झुकाव समाप्त कर दूंगा, और मूल सी-कोड अधिक प्राकृतिक लग रहा था।

+0

जीसी स्मृति के उन क्षेत्रों को स्थानांतरित नहीं करता है जो निश्चित कीवर्ड का उपयोग करके स्मृति स्थान पर पिन किए गए हैं। ** morbid जिज्ञासा के लिए –

+2

+1 ** –

+4

आप इसे पहले स्थान पर क्यों करना चाहते हैं? –

उत्तर

11

यह कभी भी इस निर्माण का उपयोग करने के लिए सुरक्षित है? मेरा मतलब ढेर पर दीर्घकालिक भंडारण के लिए है।

हां। ऐसा करना आमतौर पर मूर्ख, दर्दनाक और अनावश्यक होता है, लेकिन यह संभव है।

जो मैं समझता हूं उससे जीसी चीजों को स्थानांतरित करने के लिए स्वतंत्र है, और जब यह स्थानांतरित होने वाली किसी चीज़ के संदर्भ को अद्यतन करता है, तो क्या यह पॉइंटर्स भी अपडेट करता है?

सं। यही कारण है कि हम आपको इसे असुरक्षित के रूप में चिह्नित करते हैं।

मैं अनुमान लगा रहा हूं, जो इस निर्माण को बहुत असुरक्षित बना देगा, है ना?

सही।

मुझे यकीन है कि ऐसा करने के लिए बेहतर विकल्प हैं, लेकिन इसे मूर्खतापूर्ण जिज्ञासा कहते हैं।

निश्चित रूप से हैं।

क्या पॉइंटर आपको मूल रूप से इंगित करने के लिए इंगित करने की गारंटी देता है?

जब तक आप यह सुनिश्चित न करें कि ऐसा न हो। ऐसा करने के दो तरीके हैं।

वे एक: कचरा कलेक्टर को स्मृति को स्थानांतरित करने के लिए कहें। ऐसा करने के दो तरीके हैं:

  • "निश्चित" कथन के साथ एक चर को ठीक करें।

  • उन संरचनाओं के लिए एक जीसी हैंडल बनाने के लिए इंटरऑप सेवाओं का उपयोग करें जिन्हें आप जिंदा रखना चाहते हैं और एक ही स्थान पर।

इन बातों में से किसी कर कचरा कलेक्टर के प्रदर्शन उच्च संभावना मलबे के साथ होगा।

वे दो: कचरा कलेक्टर संभवतः स्थानांतरित हो सकता है कि स्मृति के संदर्भ न लें। ऐसा करने के दो तरीके हैं:

  • केवल स्थानीय चर, मान पैरामीटर, या स्टैक-आवंटित ब्लॉक का पता लें।बेशक, ऐसा करने में आपको यह सुनिश्चित करने की आवश्यकता है कि पॉइंटर्स प्रासंगिक स्टैक फ्रेम से अधिक समय तक जीवित न रहें, अन्यथा, आप कचरे का संदर्भ दे रहे हैं।

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

+0

एक पूर्ण उत्तर, धन्यवाद :) मुझे लगता है कि मैं बहुत आसान "अगले नोड में एक इंडेक्स पूर्णांक स्टोर" विधि का चयन करूंगा, जो था वैसे भी करो, लेकिन हाँ, morbid जिज्ञासा। – JulianR

2

नहीं क्यों:

struct Node 
{ 
    public Node NextNode; 
} 

या कम से कम:

struct Node 
{ 
    public IntPtr NextNode; 
} 

आप fixed बयान चारों ओर संकेत ले जाने के लिए जी सी को रोकने के लिए इस्तेमाल कर सकते हैं।

+2

मुझे नहीं पता कि यह सवाल का जवाब कैसे देता है? वह पूछ रहा है कि आप किन परिस्थितियों में ऐसा करेंगे, न कि विकल्प क्या हैं। –

+3

ठीक है, तो चलिए सवाल का जवाब दें: इस निर्माण का कभी भी उपयोग न करें। –

+0

क्षमा करें, लेकिन यह वह नहीं है जो मैं पूछ रहा हूं। मुझे पता है कि ऐसा करने के अन्य तरीके हैं (पहला मेरे लिए काम नहीं करेगा), सिर्फ यह जानना है कि यह भी काम कर सकता है या नहीं। – JulianR

2

हां, कचरा कलेक्टर वस्तुओं को चारों ओर स्थानांतरित कर सकता है और नहीं, यह आपके पॉइंटर्स को अपडेट नहीं करेगा। आपको उन वस्तुओं को ठीक करने की आवश्यकता है जिन्हें आप इंगित करते हैं। अधिक जानकारी इस memory management explanation पर मिल सकती है।

आप ठीक कर सकते हैं वस्तुओं इस तरह:

unsafe { 
    fixed (byte* pPtr = object) { 
     // This will fix object in the memory 
     } 
    } 
    } 

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

+0

हां, लेकिन यह एक लिंक्ड सूची में उपयोगी होने के लिए पर्याप्त नहीं है। –

+0

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

+1

मैं निश्चित रूप से नहीं देखता कि यह उसके प्रश्न का उत्तर कैसे देता है। – ChaosPandion

0

मैं बहुत छोटा हो सकता हूं लेकिन आप सी # में पॉइंटर का उपयोग क्यों करना चाहते हैं?

क्या यह कोड स्वयं संदर्भ के लिए ठीक नहीं है?

public class Node 
{ 
    //this is by-ref 
    public Node Next; 
} 
+0

आप कर सकते थे, लेकिन वह सवाल नहीं है कि वह पूछ रहा है। :) –

2

कुछ स्पष्ट अखंडता जांच को बाहर रखा गया है। इसके साथ स्पष्ट समस्या यह है कि आपको आवश्यकता से अधिक आवंटित करना होगा क्योंकि आप बफर को पुन: आवंटित नहीं कर सकते क्योंकि कीवर्ड निश्चित का तात्पर्य है।

public unsafe class NodeList 
{ 
    fixed Node _Nodes[1024]; 
    Node* _Current; 

    public NodeList(params String[] data) 
    { 
     for (int i = 0; i < data.Length; i++) 
     { 
      _Nodes[i].Data = data[i]; 
      _Nodes[i].Next = (i < data.Length ? &_Nodes[i + 1] : null);  
     } 

     _Current = &_Nodes[0]; 
    } 

    public Node* Current() 
    { 
     return _Current++; 
    } 
} 

public unsafe struct Node 
{ 
    public String Data; 
    public Node* Next; 
} 
+0

+1 दिलचस्प। लेकिन वास्तव में बहुत उपयोगी नहीं है। – JulianR

+0

जब तक आप अपनी सूचियों को 1024 से कम रखते हैं, तब तक यह काफी उपयोगी है। – ChaosPandion

2

एक खतरनाक विचार है, लेकिन यह काम कर सकते हैं:

जब structs के अपने सरणी एक निश्चित आकार (85000 बाइट्स) यह Large Object Heap जहां ब्लॉक स्कैन किए जाते हैं और एकत्र लेकिन नहीं ले जाया गया पर आवंटित किया जाएगा से अधिक है। ..

जुड़ा हुआ लेख खतरा एक नए CLR संस्करण LOH पर सामान ले जाने के हो सकता है कि बताते हैं ...

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