다음을 통해 공유


전송 스레드 간의 예외

Visual C++에서 지 원하는 예외가 전송 를 다른 스레드.예외를 전송 하면 하나의 스레드에서 예외를 catch 한 다음 예외를 서로 다른 스레드에서 throw 될 것 같습니다 수 있습니다.예를 들어,이 기능을 사용 기본 스레드 해당 보조 스레드에서 throw 된 모든 예외를 처리 하는 곳 다중 스레드 응용 프로그램을 작성할 수 있습니다.예외 전송 병렬 프로그래밍 라이브러리 또는 시스템 생성은 대부분 개발자에 게 유용 합니다.전송을 예외를 구현 하기 위해 Visual C++ 제공의 exception_ptr 형식 및 current_exception, rethrow_exception, 및 copy_exception 함수입니다.

namespace std 
{
   typedef unspecified exception_ptr; 
   exception_ptr current_exception();
   void rethrow_exception(exception_ptr p);
   template<class E> 
       exception_ptr copy_exception(E e);
}

매개 변수

Parameter

설명

unspecified

구현 하는 데 사용 되는 지정 되지 않은 내부 클래스를 exception_ptr 형식입니다.

p

exception_ptr 예외를 참조 하는 개체입니다.

E

예외를 나타내는 클래스입니다.

e

인스턴스 매개 변수 E 클래스입니다.

반환 값

current_exception 함수 반환은 exception_ptr 는 현재 진행 중인 예외를 참조 하는 개체입니다.예외가 진행 되는 경우, 함수 반환은 exception_ptr 모든 예외와 연결 된 개체입니다.

copy_exception 함수 반환 된 exception_ptr 지정 된 예외를 참조 하는 개체는 e 매개 변수.

설명

시나리오

작업의 변수 값을 처리 하도록 확장할 수 있는 응용 프로그램을 작성 한다고 가정 합니다.이 목표를 달성 하는 작업을 수행 하는 데 필요한 만큼 많은 보조 스레드는 초기, 기본 스레드를 만듭니다의 다중 스레드 응용 프로그램을 디자인 합니다.보조 스레드 로드 균형을 조정 하 고 처리량을 향상 시키기 위해 리소스를 관리 하는 기본 스레드를 수 있습니다.작업을 분산 하 여 다중 스레드 응용 프로그램은 단일 스레드 응용 프로그램 보다 더 나은 수행 합니다.

그러나 보조 스레드 예외를 throw 하는 경우 처리 하는 기본 스레드를 합니다.보조 스레드 수에 관계 없이 일관 되 고 통합 된 방식으로 예외를 처리 하는 응용 프로그램을 때문입니다.

해결책

앞의 시나리오를 처리 하기 위해 전송 스레드 간에 예외가 C++ 표준 지원 합니다.보조 스레드에서 예외를 throw 하는 경우 해당 예외가 되는 현재 예외.실제 상황에 비유 하면 현재 예외 라고 비행에서.현재 해당 예외를 catch 하는 예외 처리기를 반환할 때까지 throw 되는 시점에서 이륙에서 되지 않습니다.

보조 스레드의 현재 예외를 catch 할 수는 catch 차단 하 고 호출을 current_exception 함수에서 예외를 저장 하는 exception_ptr 개체입니다.exception_ptr 개체는 보조 스레드 및 기본 스레드를 사용할 수 있어야 합니다.예를 들어 있는 exception_ptr 개체는 전역 뮤텍스로 액세스 제어 변수가 될 수 있습니다.용어 예외가 전송 한 스레드에 예외를 변환 하는 다른 스레드에서 액세스할 수 있는 폼을 의미 합니다.

다음에 기본 스레드를 호출 하는 rethrow_exception 추출 하 고 예외를 throw 하는 함수는 exception_ptr 개체.예외가 throw 되 면 현재 주 스레드에서 예외 됩니다.즉, 예외는 기본 스레드를 보입니다.

마지막으로 기본 스레드의 현재 예외를 catch 할 수 있는 catch 차단 하 고 처리 하거나 상위 수준의 예외 처리기에 발생 합니다.나 주 스레드에서 예외를 무시 하 고 프로세스 종료할 수 있습니다.

대부분의 응용 프로그램 예외 스레드 사이 전송 하지 않아도 됩니다.그러나이 기능은 병렬 컴퓨팅 시스템 보조 스레드, 프로세서 또는 코어 간 작업을 분할할 수 있습니다 때문에 시스템에서에서 유용 합니다.병렬 컴퓨팅 환경에서 단일 한 전용 스레드 보조 스레드에서 모든 예외를 처리할 수 및 모든 응용 프로그램에 일관성 있는 예외 처리 모델을 제공할 수 있습니다.

C + + 표준 위원회 제안에 대 한 자세한 내용은 문서 번호 N2179, "언어 지원에 대 한 전송 예외 간의 스레드" 라는 제목의 인터넷에서 검색 합니다.

예외 처리 모델 및 컴파일러 옵션

응용 프로그램의 예외 처리 모델 catch 하는 예외를 전송 수 여부를 결정 합니다.Visual C++는 C++ 예외, 구조화 된 예외 처리 (SEH) 예외와 공용 언어 런타임 (CLR) 예외를 처리할 수 있는 세 가지 모델을 지원 합니다.사용은 /EH/clr 컴파일러 옵션은 응용 프로그램의 예외 처리 모델을 지정 합니다.

컴파일러 옵션 및 프로그래밍 문을 다음 조합 에서만 예외를 전송할 수 있습니다.다른 조합은 예외를 catch 수 없거나 또는 catch 할 수 있지만 예외를 전송 수 없습니다.

  • /EHa 컴파일러 옵션 및 catch 문을 SEH 및 C++ 예외를 전송할 수 있습니다.

  • /EHa, /EHs, 및 /EHsc 컴파일러 옵션 및 catch 문 C++ 예외를 전송할 수 있습니다.

  • /CLR 또는 /CLR:pure 컴파일러 옵션 및 catch 문 C++ 예외를 전송할 수 있습니다./CLR 컴파일러 옵션 사양을 의미는 /EHa 옵션입니다.참고 컴파일러가 관리 되는 예외를 전송 지원 하지 않습니다.이 예외에서 파생 된 관리 되는 때문입니다 있는 System.Exception 클래스, 이미 공용 languange 런타임 기능을 사용 하 여 스레드 간에 이동할 수 있는 개체입니다.

    보안 정보보안 정보

    지정 하는 것이 좋습니다 있는 /EHsc 컴파일러 옵션을 유일한 C++ 예외를 catch 합니다.사용 하는 경우에 사용자가 직접 보안 위협에 노출의 /EHa 또는 /CLR 컴파일러 옵션은 catch 문을 생략 부호를 사용 하 여 예외 선언 (catch(...)).사용 하려는 것은 catch 몇 가지 특정 예외를 캡처하는 데 문.그러나 해당 catch(...) 문을 심각한 수 있습니다 예기치 않은 항목을 비롯 한 모든 C++ 및 SEH 예외를 캡처합니다.무시 또는 예기치 않은 예외를 잘못 취급 하도록 하는 경우 악성 코드 프로그램의 보안을 약화 시킵니다 수를 사용할 수 있습니다.

용도

다음 단원에서 설명 하는 예외를 사용 하 여 전송 하는 방법의 exception_ptr 형식으로 하는 current_exception, rethrow_exception, 및 copy_exception 함수.

Dd293602.collapse_all(ko-kr,VS.110).gifexception_ptr 형식

사용 된 exception_ptr 현재 예외 또는 사용자 지정 예외의 인스턴스를 참조 하는 개체입니다.예외가 표시 되며 Microsoft 구현에는 EXCEPTION_RECORD 구조체입니다.각 exception_ptr 개체의 복사본에 있는 예외 참조 필드에 포함 됩니다 있는 EXCEPTION_RECORD 예외를 나타내는 구조입니다.

때 사용자가 선언 된 exception_ptr 변수를 변수는 예외와 관련 된지 않습니다.즉, 해당 예외 참조 필드에는 NULL입니다.이러한는 exception_ptr 개체 호출에 null exception_ptr.

사용은 current_exception 또는 copy_exception 함수에 대 한 예외를 지정 하는 exception_ptr 개체입니다.에 대 한 예외 지정은 exception_ptr 변수, 변수 예외 참조 필드 예외를 복사본을 가리킵니다.메모리가 부족 하 여 예외를 복사할 경우 예외 참조 필드의 복사본을 가리키는 있는 std::bad_alloc 예외.경우는 current_exception 또는 copy_exception 함수가 어떤 다른 이유로, 함수 호출 예외를 복사할 수 없습니다를 terminate (CRT) 함수는 현재 프로세스를 종료 합니다.

그 이름에도 불구 하 고 있는 exception_ptr 개체 자체에 대 한 포인터입니다.포인터가 의미 체계를 준수 하지 고 포인터 멤버 액세스를 사용할 수 없습니다 (->) 또는 간접 참조 (*) 연산자입니다.exception_ptr 개체에 없음 공용 데이터 멤버 또는 멤버 함수만 있습니다.

비교:

등호를 사용할 수 있습니다 (==)과 같지 않음 (!=) 두 개를 비교 하는 연산자 exception_ptr 개체입니다.연산자 이진 값 (비트 패턴)을 비교 하지 않습니다는 EXCEPTION_RECORD 는 예외를 나타내는 구조입니다.연산자의 예외 참조 필드에 주소를 비교 하는 대신에 exception_ptr 개체입니다.따라서 null exception_ptr 과 NULL 값에 동일한 것으로 간주 합니다.

Dd293602.collapse_all(ko-kr,VS.110).gifcurrent_exception 함수

호출 하는 current_exception 작동을 catch 블록.비행에 예외가 있는 경우 하는 catch 블록에서 예외를 catch 수는 current_exception 함수 반환은 exception_ptr 예외를 참조 하는 개체입니다.그렇지 않으면 함수는 null을 반환 exception_ptr 개체입니다.

자세히:

current_exception 함수에서 비행 여부에 관계 없이 되는 예외를 캡처하는 catch 문을 지정은 예외 선언 문.

끝에 현재 예외에 대 한 소멸자가 호출 되는 catch 예외를 rethrow를 실행 하는 경우를 차단 합니다.그러나 사용자가 호출 하는 경우에는 current_exception 를 소멸자 함수는함수 반환은 exception_ptr 현재 예외를 참조 하는 개체입니다.

후속 호출에는 current_exception 함수 반환 exception_ptr 현재 예외의 다른 복사본을 참조 하는 개체입니다.따라서 서로 다른 복사본을 참조 하기 때문에 같은 이진 값의 복사본을 가질 경우에 개체가 동일 하지 않은 것으로 비교 합니다.

SEH 예외:

사용 하는 경우는 /EHa 컴파일러 옵션은 C++에서는 SEH 예외를 catch 할 수 있습니다 catch 블록.current_exception 함수 반환 된 exception_ptr SEH 예외를 참조 하는 개체입니다.하는 rethrow_exception 함수를 호출 하는 경우 SEH 예외를 throw는흐른 exception_ptr 인수로 개체.

current_exception 함수는 null을 반환 합니다. exception_ptr 는 SEH를 호출할 경우 __finally 종료 처리기는 __except 예외 처리기 나는 __except 필터 식을 합니다.

전송된 예외는 중첩 된 예외를 지원 하지 않습니다.중첩 된 예외는 예외를 처리 하는 동안 다른 예외가 throw 되는 경우에 발생 합니다.중첩 된 예외를 catch 하는 경우는 EXCEPTION_RECORD.ExceptionRecord 데이터 멤버의 체인을 가리키는 EXCEPTION_RECORD 연결 된 예외를 설명 하는 구조입니다.current_exception 이 반환 되므로 중첩 된 예외를 함수 지원 하지 않습니다는 exception_ptr 개체의 ExceptionRecord 데이터 멤버를 0으로 설정 합니다.

SEH 예외를 catch 하는 경우에 포인터에 의해 참조 되는 메모리를 관리 해야는 EXCEPTION_RECORD.ExceptionInformation 데이터 멤버의 배열입니다.메모리에 해당 하는 기간 동안 유효한 지를 보장 해야 exception_ptr 개체 및 메모리가 해제 될 때의 exception_ptr 개체가 삭제 됩니다.

구조적된 예외 (SE) 변환기 함수 전송 기능은 예외와 함께 사용할 수 있습니다.SEH 예외는 C++ 예외를 번역 하는 경우는 current_exception 함수 반환 된 exception_ptr 번역 된 예외는 원래 SEH 예외 대신 참조.rethrow_exception 이후에 throw 됩니다 번역 된 예외가 원래 예외 없는 함수입니다.SE 변환기 함수에 대 한 자세한 내용은 참조 하십시오. _set_se_translator.

Dd293602.collapse_all(ko-kr,VS.110).gifrethrow_exception 함수

Catch 된 예외를 저장 한 후에 exception_ptr 개체에서 기본 스레드 개체를 처리할 수 있습니다.호출 하 여 기본 스레드를의 rethrow_exception 와 함께 작동을 exception_ptr 개체를 인수로.rethrow_exception 함수에서 예외를 추출은 exception_ptr 개체 및 다음 주 스레드의 컨텍스트에서 예외를 throw 합니다.경우는 p 의 매개 변수는 rethrow_exception 함수에 null입니다 exception_ptr, 함수를 throw std::bad_exception.

추출 된 예외는 이제 주 스레드의 현재 예외 이며 다른 예외와 마찬가지로 처리할 수 있습니다.예외를 catch 하는 경우이 즉시 처리 또는 사용 하는 throw 상위 수준 예외 처리기에 보낼 수 문.그렇지 않으면 아무 작업도 수행 하지 및 기본 시스템 예외 처리기를 해당 프로세스를 종료할 수 있습니다.

Dd293602.collapse_all(ko-kr,VS.110).gifcopy_exception 함수

copy_exception 함수 인수로 클래스의 인스턴스를 사용 하 고 반환 된 exception_ptr 인스턴스를 참조 하는.일반적으로, 지정 된 예외 클래스 개체를 인수로 copy_exception 인수 클래스 개체를 사용할 수 있지만 작동.

호출 하는 copy_exception 함수에서 포착 하는 C++ 예외를 throw 하는 것과는 catch 블록을 한 다음 호출의 current_exception 를 반환 하는 함수는 exception_ptr 예외를 참조 하는 개체.Microsoft 구현에서 copy_exception 함수를 throw 한 예외를 catch 하는 것 보다 더 효율적입니다.

응용 프로그램은 일반적으로 필요 하지 않은 여 copy_exception 함수 및 우리는 사용 하지 못하게 합니다.

예제

다음 예제에서는 표준 C++ 예외와는 다른 사용자 지정 C++ 예외를 스레드를 전송합니다.

// transport_exception.cpp
// compile with: /EHsc /MD
#include <windows.h>
#include <stdio.h> 
#include <exception>
#include <stdexcept>

using namespace std;

// Define thread-specific information.
#define THREADCOUNT 2
exception_ptr aException[THREADCOUNT]; 
int           aArg[THREADCOUNT];

DWORD WINAPI ThrowExceptions( LPVOID ); 

// Specify a user-defined, custom exception. 
// As a best practice, derive your exception 
// directly or indirectly from std::exception. 
class myException : public std::exception { 
};
int main()
{
    HANDLE aThread[THREADCOUNT];
    DWORD ThreadID;

    // Create secondary threads.
    for( int i=0; i < THREADCOUNT; i++ )
    {
        aArg[i] = i;
        aThread[i] = CreateThread( 
            NULL,       // Default security attributes.
            0,          // Default stack size.
            (LPTHREAD_START_ROUTINE) ThrowExceptions, 
            (LPVOID) &aArg[i], // Thread function argument.
            0,          // Default creation flags.
            &ThreadID); // Receives thread identifier.
        if( aThread[i] == NULL )
        {
            printf("CreateThread error: %d\n", GetLastError());
            return -1;
        }
    } 

    // Wait for all threads to terminate.
    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE); 
    // Close thread handles.
    for( int i=0; i < THREADCOUNT; i++ ) {
        CloseHandle(aThread[i]); 
    }

    // Rethrow and catch the transported exceptions.
    for ( int i = 0; i < THREADCOUNT; i++ ) {
        try {
            if (aException[i] == NULL) {
                printf("exception_ptr %d: No exception was transported.\n", i);
            }
            else {
                rethrow_exception( aException[i] );
            }  
        }
        catch( const invalid_argument & ) {
            printf("exception_ptr %d: Caught an invalid_argument exception.\n", i);
        }
        catch( const myException & ) {
            printf("exception_ptr %d: Caught a  myException exception.\n", i);
        }
    }
} 
// Each thread throws an exception depending on its thread 
// function argument, and then ends. 
DWORD WINAPI ThrowExceptions( LPVOID lpParam ) 
{ 
    int x = *((int*)lpParam);
    if (x == 0) {
        try {
            // Standard C++ exception.
            // This example explicitly throws invalid_argument exception. 
            // In practice, your application performs an operation that 
            // implicitly throws an exception.
            throw invalid_argument("A C++ exception.");
        }  
        catch ( const invalid_argument & ) { 
            aException[x] = current_exception();
        } 
    }
    else {
        // User-defined exception.
        aException[x] = copy_exception( myException() ); 
    }
    return TRUE; 
}
  
  

요구 사항

헤더: <exception>

참고 항목

참조

Visual C++에서는 처리 된 예외

EXCEPTION_RECORD 구조

구문 처리기

/EH(예외 처리 모델)

/clr(공용 언어 런타임 컴파일)