2012-03-26 6 views
18

मुझे ऐसी स्थिति का सामना करना पड़ रहा है जहां CloseHandle पर एक PInvoke कॉल डीबगर के तहत चलाए जाने पर .NET 4 अनुप्रयोग में SEHException फेंक रहा है। others who have encountered similar issues migrating from 3.5 to 4 के विपरीत, मैं विशेष रूप से व्यवहार से परेशान नहीं हूं, और पहले ही समस्या को ढूंढ चुका हूं (एक थर्ड पार्टी लाइब्रेरी एक ही हैंडल पर CloseHandle दो बार कॉल कर रही है)। हालांकि, मुझे परेशान है कि यह व्यवहार .NET 3.5 एप्लिकेशन में क्यों नहीं होता है।क्लोजहैंडल से अपवादों का संचालन .NET 4 और 3.5 के बीच क्यों भिन्न है?

निम्नलिखित छोटी लेकिन पूर्ण उदाहरण व्यवहार मैं हो रही हैं (दोनों XP SP3 और 7 विन 64 पर परीक्षण किया, हमेशा 86 के रूप में संकलित) को दर्शाता है:

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      var hFileMapping = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04 /* read write */, 0, 0x1000, null); 
      CloseHandle(hFileMapping); 
      CloseHandle(hFileMapping); 
      Console.WriteLine("No exception"); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex); 
     } 

     Console.ReadKey(); 
    } 

    [DllImport("kernel32", SetLastError = true)] 
    static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName); 

    [DllImport("kernel32", SetLastError = true)] 
    static extern bool CloseHandle(IntPtr handle); 
} 

जब एक .NET 4 आवेदन के रूप में चलाने के लिए, SEHException दूसरे CloseHandle पर फेंक दिया गया है। documentation for CloseHandle के अनुसार, इस अपेक्षित व्यवहार:

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

हालांकि, जब एक .NET 3.5 आवेदन (या CLR 2.0) के रूप में संकलित, कोई अपवाद नहीं दूसरा CloseHandle कॉल पर फेंक दिया जाता है, और संदेश "No exception" छपा है।

this article के अनुसार, .NET 4 के लिए जारी किए गए अद्यतन सीएलआर में निम्न स्तर के अपवादों के साथ कुछ अलग-अलग डिफ़ॉल्ट व्यवहार हैं जिनमें प्रक्रिया स्थिति को दूषित करने की क्षमता है। हालांकि, जहां तक ​​मैं उस लेख से समझ सकता हूं, पिछले सीएलआर व्यवहार के बारे में कुछ भी नहीं बताया गया है जिससे अपवाद को पूरी तरह से अनदेखा कर दिया जाएगा।

.NET 3.5 (या सीएलआर 2.0) एप्लिकेशन .NET 4 में मौजूद CloseHandle के दस्तावेज़ व्यवहार का प्रदर्शन क्यों नहीं करता है?

+2

मैं एक के लिए खुश हूं कि एमएस ने इस क्षेत्र में कुछ सुधार किए हैं। मैंने उम्र के लिए यहां मुद्दों के साथ संघर्ष किया: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/b5b7a179-3737-4380-b6cf-843f3e71b317/ – Brannon

+0

शायद पहले .NET 4 में वे थे बस उन अपवादों को चुपचाप पकड़ना और अनदेखा करना –

+0

जो मुझे पता लगाने में दिलचस्पी है - यह क्यों हो सकता है :) – jeffora

उत्तर

9

विंडोज़ केवल एसईएच अपवाद उत्पन्न करता है जब यह देखता है कि एक डीबगर संलग्न है। एक मूल डीबगर। .NET 4 प्रबंधित डीबगर में कोई बदलाव आया था जो अब विंडोज को ऐसे डिबगर को देखता है। मुझे कोई भी सभ्य लिंक नहीं मिल रहा है जो इस नए व्यवहार के सही विवरण को दस्तावेज करता है, क्षमा करें।

संपादित करें: मुझे एक सभ्य मिला। this blog post के तल पर गोली 8:

हुड हम देशी डिबगिंग पाइपलाइन पर बनाया गया हो वी 2-compat मोड में के तहत, आईसीडी लक्ष्य प्रक्रिया के लिए पाइप लाइन ही है (चूंकि कि V2 मॉडल था जारी है), लेकिन वह पाइपलाइन अब लक्षित प्रक्रिया के साथ साझा आईपीसी ऑब्जेक्ट्स का संग्रह नहीं है, बल्कि इसके बजाय एक ही पाइपलाइन मूल डीबगर उपयोग करता है। विशेष रूप से, हम kernel32 को कॉल करके प्रक्रिया से संलग्न होते हैं! DebugActiveProcess, और हमारे प्रबंधित ईवेंट (चीजें जो परिणामस्वरूप ICorDebugManagedCallback को कॉल करती हैं) kernel32 का उपयोग कर! WaitForDebugEvent। इसका यह भी अर्थ है कि kernel32! IsDebuggerPresent अब प्रबंधित-केवल डीबगिंग करते समय सत्य लौटाता है। यह भी कर्नेल डीबगर सक्षम होने पर प्रबंधित-केवल डिबगिंग करने में समस्या से बचने का अच्छा दुष्प्रभाव होता है (ओएस किसी भी ब्रेकपॉइंट निर्देशों को मानता है जो तब होता है जब डीबगर संलग्न नहीं होता है, कर्नेल डीबगर में ब्रेक का कारण बनता है) ।

यह सिर्फ कॉस्मेटिक फिक्स बीटीडब्ल्यू नहीं है, यद्यपि रीसायकल हमलों को संभालने वाला कुछ ऐसा है जो माइक्रोसॉफ्ट के कर्मचारियों को रात में जागता रहता है। सीएलआर का .NET 4 संस्करण सीआरटी संस्करण के साथ बनाया गया है जो बफर ओवरफ्लो की जांच करता है। जब कोई पता चला, सीआरटी तुरंत कार्यक्रम को समाप्त कर देता है। कोई AppDomain.UnhandledException, यह डेस्कटॉप के लिए एक तत्काल दुर्घटना है। यह कोड हालांकि वही काम करता है जो विंडोज करता है, मूल डिबगर की जांच करें और जब कोई संलग्न हो तो ब्रेकपॉइंट उत्पन्न करें। तो यह बहुत महत्वपूर्ण था कि प्रबंधित डीबगर एक मूल की तरह दिखना शुरू कर दिया, वास्तव में दुर्घटना का निदान करने का एकमात्र तरीका।

+0

यह भी समझाएगा कि क्यों अचानक यह .NET 3.5 में तोड़ना शुरू कर देता है जब परियोजना गुणों में "डीबग मूल कोड" चुना जाता है (जिसे मैंने दूसरी बार देखा था जब इसे फिर से देखने का प्रयास किया गया था)। धन्यवाद! – jeffora

+0

यूप, पिछले संस्करणों में अप्रबंधित डीबगिंग समर्थन को चालू करने से डीबगर कॉल WaitForDebugEvent() बनाता है। –

1

इस पर वास्तव में 'अच्छा' जवाब नहीं है 3.5 3.5 एसईएच में एक बग था जो 4.0 में तय हो गया था .. यह अपवाद खा रहा था। मेरे पास एक समान समस्या थी और हमने एमएसएफटी के साथ टिकट खोला - उनका जवाब 'बगफिक्स' था।

+0

क्या आपने कनेक्ट अनुरोध खोल दिया था? यदि हां, तो क्या आप इसके लिए एक लिंक पोस्ट कर सकते हैं? –

+0

@ जॉन सैंडर्स - हंस पासेंट ने यह भी कहा कि एक बग था, जिसका मतलब है कि एक बग था, टिकट से जोड़ने से कुछ भी साबित नहीं होगा। –

+0

हमारे पास कनेक्ट नहीं है, सिर्फ एक बंद समर्थन टिकट खोला .. ऐसा लगता है कि हंस ने नीचे दिए गए विवरण के बारे में विवरण प्रदान किया है .. – XeroxDucati

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