다음을 통해 공유


관리되는 예외 사용의 기본 개념

이 항목에서는 관리되는 애플리케이션의 예외 처리에 대해 설명합니다. 즉, /clr 컴파일러 옵션을 사용하여 컴파일되는 애플리케이션입니다.

이 항목의 내용

설명

/clr 옵션을 사용하여 컴파일하는 경우 CLR 예외를 처리할 수 있으며 표준 Exception 클래스는 CLR 예외를 처리하는 데 유용한 많은 메서드를 제공하며 사용자 정의 예외 클래스의 기본 클래스로 권장됩니다.

인터페이스에서 파생된 예외 형식 catch는 /clr에서 지원되지 않습니다. 또한 공용 언어 런타임에서는 스택 오버플로 예외를 catch할 수 없습니다. 스택 오버플로 예외가 프로세스를 종료합니다.

관리되는 애플리케이션과 관리되지 않는 애플리케이션에서 예외 처리의 차이점에 대한 자세한 내용은 C++용 관리 확장에서 예외 처리 동작의 차이점을 참조 하세요.

/clr에서 예외 throw

C++ throw 식은 CLR 형식에 핸들을 throw하도록 확장됩니다. 다음 예제에서는 사용자 지정 예외 형식을 만든 다음 해당 형식의 인스턴스를 throw합니다.

// clr_exception_handling.cpp
// compile with: /clr /c
ref struct MyStruct: public System::Exception {
public:
   int i;
};

void GlobalFunction() {
   MyStruct^ pMyStruct = gcnew MyStruct;
   throw pMyStruct;
}

throw되기 전에 값 형식을 boxed해야 합니다.

// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
   int i;
};

void GlobalFunction() {
   MyValueStruct v = {11};
   throw (MyValueStruct ^)v;
}

CLR 확장에 대한 블록 시도/Catch

CLR 및 네이티브 예외를 모두 catch하는 데 동일한 try/catch 블록 구조를 사용할 수 있습니다.

// clr_exception_handling_3.cpp
// compile with: /clr
using namespace System;
ref struct MyStruct : public Exception {
public:
   int i;
};

struct CMyClass {
public:
   double d;
};

void GlobalFunction() {
   MyStruct^ pMyStruct = gcnew MyStruct;
   pMyStruct->i = 11;
   throw pMyStruct;
}

void GlobalFunction2() {
   CMyClass c = {2.0};
   throw c;
}

int main() {
   for ( int i = 1; i >= 0; --i ) {
      try {
         if ( i == 1 )
            GlobalFunction2();
         if ( i == 0 )
            GlobalFunction();
      }
      catch ( CMyClass& catchC ) {
         Console::WriteLine( "In 'catch(CMyClass& catchC)'" );
         Console::WriteLine( catchC.d );
      }
      catch ( MyStruct^ catchException ) {
         Console::WriteLine( "In 'catch(MyStruct^ catchException)'" );
         Console::WriteLine( catchException->i );
      }
   }
}

출력

In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11

C++ 개체의 해제 순서

해제는 throw 함수와 처리 함수 사이의 런타임 스택에 있을 수 있는 소멸자가 있는 모든 C++ 개체에 대해 발생합니다. CLR 형식은 힙에 할당되므로 해제가 적용되지 않습니다.

throw된 예외에 대한 이벤트 순서는 다음과 같습니다.

  1. 런타임은 적절한 catch 절을 찾거나 SEH의 경우 예외를 catch하기 위해 SEH에 대한 필터를 제외한 스택을 안내합니다. Catch 절은 먼저 어휘 순서로 검색된 다음 호출 스택 아래로 동적으로 검색됩니다.

  2. 올바른 처리기가 발견되면 스택이 해당 지점으로 해제됩니다. 스택의 각 함수 호출에 대해 로컬 개체가 소멸되고 __finally 블록이 대부분의 중첩된 바깥쪽에서 실행됩니다.

  3. 스택이 해제되면 catch 절이 실행됩니다.

관리되지 않는 형식 잡기

관리되지 않는 개체 형식이 throw되면 형식 SEHException을 제외하고 래핑됩니다. 적절한 catch 절을 검색할 때는 두 가지 가능성이 있습니다.

  • 네이티브 C++ 형식이 발견되면 예외가 래핑 해제되고 발생한 형식과 비교됩니다. 이 비교를 통해 네이티브 C++ 형식을 일반적인 방식으로 catch할 수 있습니다.

  • 그러나 SEHException 형식의 절 또는 해당 기본 클래스를 먼저 검사하는 경우 catch 절은 예외를 가로채게 됩니다. 따라서 네이티브 C++ 형식을 catch하는 모든 catch 절을 CLR 형식의 catch 절 앞에 먼저 배치해야 합니다.

다음 사항에 유의하십시오.

catch(Object^)

catch(...)

는 모두 SEH 예외를 포함하여 throw된 모든 형식을 catch합니다.

관리되지 않는 형식이 catch된 경우 catch(Object^) throw된 개체는 삭제되지 않습니다.

관리되지 않는 예외를 throw하거나 catch하는 경우 /EHs 또는 /EHa 대신 /EHsc 컴파일러 옵션을 사용하는 것이 좋습니다.

참고 항목

예외 처리
safe_cast
예외 처리