2011-08-14 10 views
5

मैं वर्तमान में कुछ सी #/सी ++ कोड पर काम कर रहा हूं जो आवेषण का उपयोग करता है।सी #+ पॉइंटर्स को सी # में रखना सुरक्षित है?

void SetName(char* name, int idx) 

लेकिन अब मैं, यह सोच कर के बाद से मैं कर रहा हूँ: सी ++ पक्ष में एक std :: वेक्टर संकेत दिए गए प्रत्येक सी # कोड से सूचकांक से पहचान का पूरा, उदाहरण के लिए एक समारोह घोषणा इस प्रकार दिखाई देगा नहीं है संकेत के साथ काम कर हूँ मैं करने के लिए सी # कोड में सूचक पता ही नहीं भेजा जा सकता था तो मैं कुछ इस तरह कर सकता है: कि की एक त्वरित संस्करण है

void SetName(char*name, int ptr) 
{ 
    ((TypeName*)ptr)->name = name; 
} 

जाहिर है कि मैं क्या कर रहा हूँ पर हो रही है (और शायद नहीं होगा संकलन)।

क्या सूचक पते को सी ++ में स्थिर रहने की गारंटी दी जाएगी जैसे कि मैं सुरक्षित रूप से अपना पता सी # में संग्रहीत कर सकता हूं या यह किसी कारण से बहुत अस्थिर या खतरनाक होगा?

+4

बस स्पष्ट करने के लिए: आप जानते हैं कि उपर्युक्त कोड सी # में संकलित होगा यदि यह 'असुरक्षित' ब्लॉक के अंदर है? –

उत्तर

2

हां, कोई समस्या नहीं। मूल मेमोरी आवंटन कभी भी सी # पक्ष पर इंटप्राटर में पॉइंटर को संग्रहीत करने के लिए ठीक नहीं होता है। आपको लगता है कि इस सूचक रिटर्न pinvoked समारोह के कुछ प्रकार है, तो

[DllImport("something.dll", CharSet = CharSet.Ansi)] 
void SetName(IntPtr vector, string name, int index); 

कौन सा जानबूझकर ++ समारोह इस सी के बारे में निहित है की जरूरत है:

void SetName(std::vector<std::string>* vect, const char* name, int index) { 
    std::string copy = name; 
    (*vect)[index] = copy; 
} 

नोट नई सी ++ कोड में का उपयोग, आप करने के लिए है स्ट्रिंग स्ट्रिंग।पास नाम पिनवोक मार्शलर द्वारा आवंटित बफर को तर्क बिंदु और केवल फ़ंक्शन बॉडी की अवधि के लिए मान्य है। आपका मूल कोड काम नहीं कर सकता है। यदि आप वेक्टर <> पॉइंटर्स को पॉइंटर्स वापस करने का इरादा रखते हैं तो तत्व बहुत सावधान रहें। जब आप तत्व जोड़ते हैं तो एक वेक्टर अपने आंतरिक सरणी को फिर से आवंटित करता है। इस तरह का एक लौटा सूचक तब अमान्य हो जाएगा और जब आप इसे बाद में उपयोग करेंगे तो आप ढेर को भ्रष्ट कर देंगे। सी # सूची <> के साथ सटीक वही बात होती है लेकिन पॉइंटर्स को लटकने के जोखिम के बिना।

+2

वैसे, सी ++ में 'नया' का उपयोग पूरी तरह से गलत है। यह सिर्फ 'vect [index] = name होना चाहिए; '। और मुझे यह भी यकीन नहीं है कि क्या पॉइंटर वास्तव में एक संदर्भ है, यह भी सुरक्षित है। – Puppy

+0

फिक्स्ड। स्ट्रिंग की प्रतिलिपि का प्रदर्शन करना महत्वपूर्ण था। और हाँ, यह सुरक्षित है। –

+0

यह वास्तव में नहीं है कि मैं * बेहतर * के रूप में परिभाषित करता हूं। जैसे, आपने एक समस्या का आदान-प्रदान किया है कि संकलक आपको बताएगा कि आप किसी समस्या के लिए गलत हैं, जब आप ढेर भ्रष्टाचार प्राप्त करेंगे तो कच्चे पॉइंटर्स असुरक्षित रूप से असुरक्षित हैं और आपने इसे दुर्घटना से हटा दिया है या इसे लीक कर दिया है। कोई भी जो मूल सी ++ पढ़ सकता है वह 'std :: vector ' स्टोर करेगा और केवल 'vect [index] = name;' और 'पता करें कि यह एक प्रतिलिपि बनाता है। कम से कम एक स्मार्ट सूचक या कुछ का उपयोग करें। कृप्या। उदाहरण के रूप में खराब कोड डालने से अन्य लोगों को गलत चीजें सिखा रही हैं। – Puppy

1

मुझे लगता है कि यह तब तक स्थिर है जब तक आप सी ++ कोड को कम नहीं करते हैं और पूरी तरह से जानते हैं कि वह क्या करता है, और अन्य डेवलपर जो उसी कोड पर काम करते हैं, उस खतरे के बारे में भी जानते हैं।

तो मेरी राय से, यह वास्तुकला का बहुत सुरक्षित तरीका नहीं है, और जितना मैं कर सकता हूं उससे बचूंगा।

सम्मान।

7

सी # में, आपको यहां एक सूचक का उपयोग करने की आवश्यकता नहीं है, आप केवल एक सादा सी # स्ट्रिंग का उपयोग कर सकते हैं।

[DllImport(...)] 
extern void SetName(string name, int id); 

यह काम करता है क्योंकि पी/आह्वान में तार के डिफ़ॉल्ट व्यवहार है, जो एक सी शैली चार में धर्मान्तरित * MarshalAs(UnmanagedType.LPStr) उपयोग करने के लिए है। आप प्रत्येक तर्क को सी # घोषणा में स्पष्ट रूप से चिह्नित कर सकते हैं यदि उसे प्रतिबिंबित करने के किसी अन्य तरीके की आवश्यकता है, उदाहरण के लिए, [MarshalAs(UnmanagedType.LPWStr)], एक तर्क के लिए जो 2-बाइट प्रति वर्ण स्ट्रिंग का उपयोग करता है।

पॉइंटर्स का उपयोग करने का एकमात्र कारण यह है कि यदि आपको फ़ंक्शन कहने के बाद इंगित डेटा तक पहुंच बनाए रखने की आवश्यकता है। फिर भी, आप अधिकतर समय out पैरामीटर का उपयोग कर सकते हैं।

आप पॉइंटर्स की आवश्यकता के बिना मूल रूप से कुछ भी पी/आवेक कर सकते हैं (और इस प्रकार असुरक्षित कोड की आवश्यकता के बिना, जिसके लिए कुछ वातावरण में विशेषाधिकार प्राप्त निष्पादन की आवश्यकता होती है)।

1

सी # जीसी चीजें ले जाता है, लेकिन सी ++ ढेर एक आवंटित वस्तु के लिए एक सूचक कुछ भी नहीं ले गारंटी वैध जब तक आप delete यह रहने के लिए है। इस स्थिति के लिए सबसे अच्छा आर्किटेक्चर सिर्फ इंटीपीआरटी के रूप में पॉइंटर को सी # भेजना है और फिर उसे सी ++ में वापस ले जाना है।

यह निश्चित रूप से अविश्वसनीय रूप से बीएडी, हॉरिफिक पूर्णांक कलाकारों की तुलना में एक विशाल, अविश्वसनीय रूप से बेहतर विचार है जो आप वहां जा रहे हैं।

+0

सी # जीसी हालांकि तारों को स्थानांतरित नहीं करता है। – Grozz

+1

@Grozz - यह निश्चित रूप से करता है, हर स्ट्रिंग को प्रशिक्षित नहीं किया जाता है। –

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