2015-09-27 5 views
7

निम्नलिखित कोड में, फ़ंक्शन foo एक बार फिर से बार-बार कॉल करता है। आंतरिक कॉल एक पहुंच उल्लंघन का कारण बनता है। बाहरी कॉल अपवाद पकड़ता है।क्या __Finally EXCEPTION_CONTINUE_SEARCH के बाद चलाना चाहिए?

#include <windows.h> 
#include <stdio.h> 

void foo(int cont) 
{ 
    __try 
    { 
     __try 
     { 
      __try 
      { 
       if (!cont) 
        *(int *)0 = 0; 
       foo(cont - 1); 
      } 
      __finally 
      { 
       printf("inner finally %d\n", cont); 
      } 
     } 
     __except (!cont? EXCEPTION_CONTINUE_SEARCH: EXCEPTION_EXECUTE_HANDLER) 
     { 
      printf("except %d\n", cont); 
     } 
    } 
    __finally 
    { 
     printf("outer finally %d\n", cont); 
    } 
} 

int main() 
{ 
    __try 
    { 
     foo(1); 
    } 
    __except (EXCEPTION_EXECUTE_HANDLER) 
    { 
     printf("main\n"); 
    } 
    return 0; 
} 

यहाँ की उम्मीद उत्पादन हालांकि, outer finally 0 सुस्पष्ट वास्तविक उत्पादन से लापता है

inner finally 0 
outer finally 0 
inner finally 1 
except 1 
outer finally 1 

होना चाहिए। क्या यह एक बग है या क्या कुछ विवरण है जो मैं देख रहा हूं?

पूर्णता के लिए, x64 के लिए संकलन VS2015 के साथ होता है। आश्चर्यजनक रूप से यह x86 पर नहीं होता है, जिससे मुझे विश्वास होता है कि यह वास्तव में एक बग है।

+0

यह तकनीकी रूप से अपरिभाषित व्यवहार के दायरे में पड़ सकता है, क्योंकि आप एक शून्य सूचक को असाइन कर रहे हैं। क्या आपने 'RaiseException' का उपयोग करके नियमित अपवाद फेंकने की कोशिश की है? – OmnipotentEntity

+1

अच्छा, अच्छा नहीं है। यह एक नया मुद्दा नहीं है, वीएस2013 वही तरीके से व्यवहार करता है। ऐसा लगता है कि मेरे लिए सुरक्षात्मक सीमा/सुरक्षा, रिकर्सन के लिए विशिष्ट है, यह एक गैर-पुनरावर्ती मामले में ठीक काम करता है। बहुत संदिग्ध कोई भी इस समस्या को ठीक कर सकता है, इसके बारे में connect.microsoft.com को पिंग करने के लिए सबसे अच्छा है। –

+0

@ ओमनीपोटेंट एंटीटी: एक शून्य सूचक को असाइन करना * अपरिभाषित व्यवहार * है, जहां तक ​​सी ++ भाषा मानक का संबंध है। विंडोज प्लेटफार्म पर, हालांकि, यह अच्छी तरह परिभाषित है: निर्देश एक प्रवेश उल्लंघन बढ़ाता है, जिसे एक एसईएच अपवाद के माध्यम से उपयोगकर्ता कोड को सूचित किया जाता है। – IInspectable

उत्तर

0

मौजूद हैं और अधिक बस उदाहरण (हम भीतरी try/finally ब्लॉक निकाल सकते हैं:।

void foo(int cont) 
{ 
    __try 
    { 
     __try 
     { 
      if (!cont) *(int *)0 = 0; 
      foo(cont - 1); 
     } 
     __except (cont? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
     { 
      printf("except %d\n", cont); 
     } 
    } 
    __finally 
    { 
     printf("finally %d\n", cont); 
    } 
} 
उत्पादन के साथ

except 1 
finally 1 

तो finally 0 ब्लॉक निष्पादित नहीं लेकिन पुनरावर्ती नहीं मामले में - कोई बग:

__try 
{ 
    foo(0); 
} 
__except(EXCEPTION_EXECUTE_HANDLER) 
{ 
    printf("except\n"); 
} 

आउटपुट:

finally 0 
except 

इस

अगले समारोह में बग है

EXCEPTION_DISPOSITION 
__C_specific_handler (
    _In_ PEXCEPTION_RECORD ExceptionRecord, 
    _In_ PVOID EstablisherFrame, 
    _Inout_ PCONTEXT ContextRecord, 
    _Inout_ PDISPATCHER_CONTEXT DispatcherContext 
    ); 
बग here के साथ इस समारोह की

वर्ष कार्यान्वयन:

    // 
        // try/except - exception filter (JumpTarget != 0). 
        // After the exception filter is called, the exception 
        // handler clause is executed by the call to unwind 
        // above. Having reached this point in the scan of the 
        // scope tables, any other termination handlers will 
        // be outside the scope of the try/except. 
        // 

        if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) { // bug 
         break; 
        } 

हम नवीनतम कुलपति संकलक/पुस्तकालयों स्थापित किया है, तो खोज के लिए, chandler.c (\VC\crt\src\amd64\chandler.c पर स्थित मेरे इंस्टॉल में)

कुछ मामले में

   if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget 
        // Terminate only when we are at the Target frame; 
        // otherwise, continue search for outer finally: 
        && IS_TARGET_UNWIND(ExceptionRecord->ExceptionFlags) 
        ) { 
        break; 
       } 

तो अतिरिक्त शर्त IS_TARGET_UNWIND(ExceptionRecord->ExceptionFlags) जो इस बग

__C_specific_handler (अलग CRT पुस्तकालयों में लागू स्थिर लिंक के साथ कुछ मामले में तय जोड़ा जाता है,:

और फाइल में अब अगले कोड देख सकते हैं vcruntime*.dll या msvcrt.dll से आयात किया जाएगा (ntdll.dll पर भेजा गया था))। ntdll.dll इस फ़ंक्शन को निर्यात करें - हालांकि नवीनतम Win10 बिल्ड (14393) में यह अभी भी

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