C++ 예외는 COM 모듈 경계를 통과 할 수 없습니다.COM 메서드 경계에서 잠재적으로 throw하는 C++ 코드
STDMETHODIMP CSomeComServer::DoSomething()
{
CppDoSomething(); // <--- This may throw C++ exceptions
return S_OK;
}
:
그래서, 우리는 COM 방법 본체에 있고,라고 일부 C++ 잠재적으로 던지는 방법/기능 (예 : STL 클래스가 사용되기 때문에이 던질 수) 가정 Q1. 위의 코드는 실행 가능한 구현입니까? 예를 들어, 해당 코드가 컨텍스트 메뉴 셸 확장의 일부인 경우 C++ CppDoSomething()
함수가 C++ 예외를 throw하면 Explorer는 무엇을합니까? C++ 예외를 잡아서 셸 확장을 언로드합니까? 오류 빠른 접근 방식을 따르는 Explorer (크래시 덤프를 사용하여 문제를 분석하는 것이 가능함)가 작동하지 않습니까?
질문 2. 이와 같은 구현이 더 좋을까요?
STDMETHODIMP CSomeComServer::DoSomething()
{
//
// Wrap the potentially-throwing C++ code call in a safe try/catch block.
// C++ exceptions are caught and transformed to HRESULTs.
//
try
{
CppDoSomething(); // <--- This may throw C++ exceptions
return S_OK;
}
//
// Map C++ std::bad_alloc exception to E_OUTOFMEMORY HRESULT.
//
catch(const std::bad_alloc& ex)
{
// ... Log the exception what() message somewhere,
// e.g. using OutputDebugString().
....
return E_OUTOFMEMORY;
}
//
// Map C++ std::exception exception to generic E_FAIL.
//
catch(const std::exception& ex)
{
// ... Log the exception what() message somewhere,
// e.g. using OutputDebugString().
....
return E_FAIL;
}
}
3. 또는 C++ 예외가 발생하면 더 이상 작동하지 않을 수있는 상태로 COM 서버를 배치하기 위해 내부 플래그 (예 : bool m_invalid
데이터 멤버)를 설정하는 것이 더 좋을 것입니다. 따라서 모든 연속 호출은 해당 메서드는 E_FAIL
또는 다른 특정 오류 같은 일부 오류 코드를 반환합니까?
4. 마지막으로, Q2/Q3이 좋은 구현 가이드 라인이라고 가정하면 편리한 전 처리기 매크로 (모든 COM 메서드 본문에서 다시 사용할 수 있음)에서 자세한 정보 try/catch
을 숨길 수 있습니다.
#define COM_EXCEPTION_GUARD_BEGIN try \
{
#define COM_EXCEPTION_GUARD_END return S_OK; \
} \
catch(const std::bad_alloc& ex) \
{ \
.... \
return E_OUTOFMEMORY; \
} \
catch(const std::exception& ex) \
{ \
.... \
return E_FAIL; \
}
//
// May also add other mappings, like std::invalid_argument --> E_INVALIDARG ...
//
STDMETHODIMP CSomeComServer::DoSomething()
{
COM_EXCEPTION_GUARD_BEGIN
CppDoSomething(); // <--- This may throw C++ exceptions
COM_EXCEPTION_GUARD_END
}
STDMETHODIMP CSomeComServer::DoSomethingElse()
{
COM_EXCEPTION_GUARD_BEGIN
CppDoSomethingElse(); // <--- This may throw C++ exceptions
COM_EXCEPTION_GUARD_END
}
다른 뭔가 상기 전처리 매크로를 대체하는 현대 C++ 14분의 11, 그것은 수를 사용하여, 더 편리하고, 더 우아하고, 더 좋아?
* COM 경계에서 C++ 예외 (또는 거의 다른 유형)를 throw하지 마십시오. HRESULT가 그 것이다. 더 많은 정보를 원한다면'IErrorInfo'와'ISupportsErrorInfo' 패러다임을 고려하십시오. 마지막 스 니펫의 매크로에 관해서는, 당신의 부분에 대한 디자인 결정이지만, 한 가지 또는 다른 것이 COM 멤버를 버리지는 않습니다 *. – WhozCraig
@WhozCraig : C++ 예외 (예 :'std :: bad_alloc','std :: invalid_argument','std :: runtime_error', ...) "핵심"C + + 코드에서 던져 질 및 COM 메서드 본문에서'try/catch' 블록에 걸린 경우 COM 서버를 특별한 _ "잘못된 상태"_에 넣고 다음 메서드 호출을 실패하게 만들겠습니까? 아니면 예외를 오류'HRESULT'에 매핑하고 고객 서비스를 계속 하시겠습니까? –
catch 된 예외의 심각도는 상황에 대해서만 평가할 수 있습니다. 이렇게하면 COM 서버를 복구 할 수없는 오류 모드로 만들지 여부를 각 호출에 대해 결정해야합니다. C++ 예외를 사용할 때 * 강력한 보증 *을 구현하는 것이 도움이됩니다. 즉, 작업이 완료 될 때 실행되거나 실패시 모든 일시적인 상태 수정을 롤백합니다. – IInspectable