다음을 통해 공유


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

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

이 항목의 내용

설명

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

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

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

clr에서의 예외 던지기

C++ throw 식은 CLR 형식에 핸들을 던지도록 확장됩니다. 다음 예제에서는 사용자 지정 예외 형식을 만든 다음 해당 형식의 인스턴스를 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되기 전에 값 형식을 박싱해야 합니다.

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

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

CLR 확장용 시도/예외 처리 블록

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 형식은 힙에 할당되므로 해제가 적용되지 않습니다.

던져진 예외에 대한 이벤트 순서는 다음과 같습니다.

  1. 런타임은 적절한 catch 절이나 SEH의 경우 예외를 처리하기 위한 SEH의 except 필터를 찾기 위해 스택을 탐색합니다. Catch 절은 먼저 사전적 순서로 검색된 다음 호출 스택 아래로 동적으로 탐색됩니다.

  2. 올바른 처리기가 발견되면 스택이 해당 지점으로 되감아집니다. 스택의 각 함수 호출에 대해 로컬 개체가 파괴되고, 가장 안쪽 중첩부터 바깥쪽으로 __finally 블록이 실행됩니다.

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

관리되지 않는 형식 잡기

관리되지 않는 개체 형식이 throw될 때 해당 개체는 형식 SEHException의 예외로 감싸집니다. 적절한 catch 절을 검색할 때는 두 가지 가능성이 있습니다.

  • 네이티브 C++ 형식을 만나면, 예외가 풀리고 발견된 형식과 비교됩니다. 이 비교를 통해 네이티브 C++ 형식을 정상적인 방법으로 포착할 수 있습니다.

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

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

catch(Object^)

catch(...)

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

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

관리되지 않은 예외를 throw하거나 catch할 때는 /EHsc 컴파일러 옵션을 /EHs 또는 /EHa 대신에 사용하는 것을 권장합니다.

참고 항목

예외 처리
safe_cast
예외 처리