2010-08-29 12 views
6

पकड़ने मैं एक StackOverflowException कैसे पकड़ करते हैं?एक StackOverflowException

मेरे पास एक ऐसा प्रोग्राम है जो उपयोगकर्ता को स्क्रिप्ट लिखने की अनुमति देता है, और जब मनमाने ढंग से उपयोगकर्ता-कोड चलाता है तो मुझे StackOverflowException मिल सकता है। दिखा रहे उपयोगकर्ता कोड स्पष्ट रूप से के साथ एक try घिरा हुआ है - catch, लेकिन ढेर अतिप्रवाह सामान्य परिस्थितियों में uncatchable हैं।

मैं देख ली है और this सबसे जानकारीपूर्ण जवाब मैं मिल सकता है, लेकिन अब भी मुझे एक मरे हुए अंत करने के लिए नेतृत्व किया; एक article in the BCL team's blog से मैंने पाया कि मैं RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup का उपयोग करना चाहिए कोड और प्रतिनिधि है कि एक ढेर अतिप्रवाह के बाद भी बुलाया जायेगा कॉल करने के लिए, लेकिन जब कोशिश कर रहा है, इस प्रक्रिया प्रतिनिधि कभी कहा जाता है बिना ढेर अतिप्रवाह संदेश के साथ समाप्त हो जाता है। मैंने हैंडलर विधि पर PrePrepareMethodAttribute जोड़ने का प्रयास किया है लेकिन इससे कुछ भी नहीं बदला है।

मैंने ऐपडोमेन का उपयोग करने और UnhandledException और DomainUnload ईवेंट दोनों को संभालने का भी प्रयास किया है - लेकिन पूरी प्रक्रिया स्टैक ओवरफ़्लो पर मारे जाती है। एक ही है, भले ही मैं throw new StackOverflowException(); मैन्युअल रूप से और न कि वास्तविक ढेर अतिप्रवाह प्राप्त होता है।

+0

क्या आपके पास ऐसा प्रोग्राम है जो कुछ मनमानी प्रक्रिया को स्वचालित करने के लिए स्क्रिप्ट का उपयोग कर सकता है, या क्या आपका प्रोग्राम स्क्रिप्ट के लिए एक टेक्स्ट एडिटर है? क्या आपका "मनमाना उपयोगकर्ता-कोड" स्वयं एक स्क्रिप्ट या किसी प्रकार का आईएल प्लग-इन है? –

+0

अभी मेरा प्रोग्राम भाषा के लिए एक आरईपीएल (रीड-इवल-प्रिंट लूप) है। – configurator

उत्तर

0

आप एक अलग प्रक्रिया में कोड को चलाने के लिए की जरूरत है।

+1

तब उपयोगकर्ता को अभी भी प्रक्रिया दुर्घटना दिखाई देगी, जिसमें उन परिस्थितियों में होने वाली परेशान विंडोज स्क्रीन भी शामिल है। मैं उस स्थिति को रोकने के लिए मूल प्रक्रिया से उस स्थिति का पता कैसे लगाऊंगा? – configurator

2

आपके कोड द्वारा नियंत्रित अपवाद को संभालने के लिए, आप AppDomains UnhandledException की सदस्यता ले सकते हैं - यह ऑपरेटिंग सिस्टम संभालता है जब यह संवाद प्रदर्शित करता है कि प्रोग्राम अप्रत्याशित रूप से बाहर निकलता है।

में अपने कार्यक्रम के मुख्य विधि का उपयोग

वर currentDomain = AppDomain.CurrentDomain;

और फिर घटना

currentDomain.UnhandledException + = हैंडलर के लिए एक हैंडलर जोड़ने;

हैंडलर आप इस तरह के रूप में कुछ भी लॉग आप चाहते हैं, कर सकते हैं में, एक त्रुटि प्रदर्शित करते हैं, या यहां तक ​​कि कार्यक्रम reinitializing अगर वांछित।

+0

आप सही हैं, और यह पहली बात है जिसकी मैंने कोशिश की - लेकिन यह काम नहीं किया। मैंने इसे प्रश्न में जोड़ा है। – configurator

2

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

+0

ऐसा लगता है जैसे वह कच्चे आईएल चला रहा है, न कि अपने स्वयं के दुभाषिया। – SLaks

+0

वास्तव में, मैं अपना खुद का दुभाषिया चला रहा हूं। लेकिन अगर मैं संभव हो, तो एक समाधान जो कच्चे आईएल के लिए भी काम करता है। – configurator

+0

इसके अलावा, एक स्क्रिप्ट किसी भी .net फ़ंक्शन को कॉल कर सकती है - जिसका अर्थ है कि मैं कॉल पथ को बहुत अच्छी तरह से सुरक्षित नहीं कर सकता। – configurator

0

आपको एक अलग ऐप डोमेन में उपयोगकर्ता स्क्रिप्ट या किसी बाहरी तृतीय पक्ष प्लगइन को लोड करना होगा, ताकि आप डोमेन को सुरक्षित रूप से अनलोड कर सकें, एक अप्राप्य त्रुटि होनी चाहिए।

आपको एक अलग AppDomain बनाना होगा क्योंकि आप लोड किए गए डोमेन से असेंबली को अनलोड नहीं कर सकते हैं, और आप अपना मुख्य एप्लिकेशन डोमेन बंद नहीं करना चाहते हैं।

var scriptDomain = AppDomain.CreateDomain("User Scripts"); 

फिर आप एक विधानसभा है कि आप बनाने की जरूरत से किसी भी प्रकार लोड कर सकते हैं:

आप इस तरह एक नया आवेदन डोमेन बना। आपको यह सुनिश्चित करना होगा कि जिस वस्तु को आप MarshalByRefObject से प्राप्त करेंगे।

मुझे लगता है कि अपने उपयोगकर्ता स्क्रिप्ट एक वस्तु इस तरह परिभाषित अंदर लपेटा जाता है:

public abstract UserScriptBase : MarshaByRefObject 
{ 
    public abstract void Execute(); 
} 

इसलिए इस तरह के किसी भी उपयोगकर्ता स्क्रिप्ट लोड कर सकते हैं:

object script = domain.CreateInstanceFromAndUnwrap(type.Location, type.FullName); 

सब उसके बाद, आप सदस्यता ले सकते हैं scriptDomain.UnhandledException पर और किसी भी अप्राप्य त्रुटि की निगरानी करें।

एक अलग एप्लिकेशन डोमेन का उपयोग करना आसान नहीं है और आपको शायद कुछ लोडिंग/अनलोडिंग समस्या का सामना करना पड़ेगा (डीएलएल दोनों डोमेन द्वारा संदर्भित है)।

मैं आपको सलाह देता हूं कि आप some tutorial साथी जो आपको ऑनलाइन मिल सके।

+2

यह मदद करने के लिए नहीं जा रहा है। 'StackOverflowException' पूरी प्रक्रिया को समाप्त करता है, भले ही इसमें 'AppDomain' हुआ है। –

+0

मैं सहमत हूं कि यह एक अच्छा विचार है, लेकिन दुर्भाग्यवश यह काम नहीं करता है ... – configurator

+0

@configurator, यह एक अच्छा विचार कैसा है अगर यह काम नहीं करता है? शायद यह चालाक या जटिल है, लेकिन महान नहीं है। – JMCF125

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