2010-05-13 7 views
5

मेरे पास एक एक्सएनए 3.0 प्रोजेक्ट है जो VS2008 में ठीक है, लेकिन यह वीएस -2010 (एक्सएनए 4.0 सीटीपी के साथ) में संकलन त्रुटियों को देता है। त्रुटि:"लैम्ब्डा अभिव्यक्ति के अंदर निश्चित स्थानीय का उपयोग नहीं कर सकता"

Cannot use fixed local 'depthPtr' inside an anonymous method, lambda expression, or query expression

depthPtr एक सरणी में एक fixed float* कि System.Threading से एक Parallel.For लैम्ब्डा अभिव्यक्ति के अंदर इस्तेमाल किया जाता है,। जैसा कि मैंने कहा, यह संकलित और VS2008 पर ठीक है, लेकिन यह .NET 3.5 को लक्षित करते समय भी VS2010 पर नहीं है।

क्या यह .NET 4.0 में बदल गया है, और फिर भी, क्या यह अभी भी संकलित नहीं होना चाहिए जब मैं .NET 3.5 को लक्ष्य ढांचे के रूप में चुनता हूं? "निश्चित स्थानीय का उपयोग नहीं कर सकता" शब्द की खोज Google और Bing दोनों में बिल्कुल एक (बेकार) परिणाम उत्पन्न करती है।

यदि यह बदल गया है, तो इसका कारण क्या है? मैं कल्पना कर सकता हूं कि fixed पॉइंटर-प्रकार को बंद करने में कैप्चरिंग थोड़ा अजीब हो सकता है, यही कारण है कि? तो मुझे लगता है कि यह बुरा अभ्यास है? और इससे पहले कि कोई पूछता है: नहीं, पॉइंटर्स का उपयोग यहां बिल्कुल महत्वपूर्ण नहीं है। मैं अभी भी जानना चाहते हैं, हालांकि :)

संपादित करें: अनुरोध किया के रूप में, एक कोड नमूना (स्पष्ट रूप से मेरा कार्यक्रम से नहीं,) जो त्रुटि reproduces: (VS2008 में

static unsafe void Main(string[] args) 
{ 
    float[] array = new float[10]; 

    fixed (float* ptr = array) 
    { 
    Parallel.For(0, 10, i => 
    { 
     ptr[i] = i; 
    }); 
    } 
} 

ऊपर compiles अच्छी तरह से, Parallel के संदर्भ से अलग, लेकिन कोई अन्य लैम्ब्डा अभिव्यक्ति करेगा), लेकिन वीएस -2010 में नहीं है।

+1

क्या आप कोड को पोस्ट कर सकते हैं जो त्रुटि का कारण बनता है। – luke

+0

ठीक है, पोस्ट करने के लिए बहुत कुछ नहीं है, यह वास्तव में त्रुटि क्या है: एक lamdba अभिव्यक्ति के अंदर एक सूचक का उपयोग। – JulianR

+0

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

उत्तर

3

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

+0

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

+0

मुझे नहीं लगता कि सभी परिदृश्यों को स्थिर रूप से जांचना संभव होगा, एक पिन पॉइंटर अमान्य हो सकता है, अंततः कोई हमेशा जीसीएचंडल का उपयोग कर सकता है। यह जांच शायद इस तरह के कोड से उत्पन्न होने वाली गैर-स्पष्ट समस्याओं से बचने के लिए "सर्वोत्तम प्रयास" का प्रतिनिधित्व करती है। –

0

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

1

doco कहता है कि आपको अज्ञात विधियों में असुरक्षित कोड तक पहुंचने की अनुमति नहीं है, और वही प्रतिबंध लैम्बडा पर लागू होते हैं, इसलिए मुझे लगता है कि यह आपकी समस्या हो सकती है। क्या आपके पास वास्तविक कंपाइलर त्रुटि नहीं है?

1

यह काम करता है। असल में हमने लैम्ब्डा को असुरक्षित पॉइंटर से हटा दिया और fixed ब्लॉक के अंदर घोषित कक्षा के उदाहरण के लिए इसे एक प्रतिनिधि के साथ बदल दिया।

static unsafe void UnsafeTest(string[] args) { 
     float[] array = new float[10]; 

     fixed(float* ptr = array) { 
      UnsafeOps ops = new UnsafeOps(); 
      ops.p = ptr; 

      Parallel.For(0, 10, ops.Lambda); 
     } 
    } 

    unsafe class UnsafeOps { 
     public float* p; 
     public unsafe void Lambda(int value) { 
      p[value] = value; 
     } 
    } 

मेरे लिए ऐसा लगता है कि नेट 4 संकलक में तय स्मृति पहुँच अनुमति न देने पर कुछ आधा arsed प्रयास गयी। उपरोक्त कोड ब्लॉक में आप fixed ब्लॉक के बाहर UnsafeOps को परिभाषित कर सकते हैं और fixed ब्लॉक के बाद सरणी तक पहुंच सकते हैं। तो यह सही नहीं है ...

1

संकलक उस कोड को अस्वीकार करने के लिए सही है। फिक्स्ड केवल स्थानीय चर पर उपयोग किया जा सकता है, और बंद होने से पकड़े गए चर स्थानीय चर नहीं हैं, वे बंद होने के लिए राज्य को बनाए रखने के लिए उपयोग की जाने वाली कक्षा में फंस गए हैं।

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