예외: 버전 3.0의 예외 매크로 변경 사항
고급 항목입니다.
MFC 버전 3.0 이상에서는 예외 처리 매크로가 C++ 예외를 사용하도록 변경되었습니다. 이 문서에서는 이러한 변경 내용이 매크로를 사용하는 기존 코드의 동작에 어떤 영향을 줄 수 있는지 설명합니다.
이 문서에서는 다음 항목을 다룹니다.
예외 형식 및 CATCH 매크로
이전 버전의 MFC 에서 CATCH 매크로는 MFC 런타임 형식 정보를 사용하여 예외의 형식을 확인했습니다. 즉, catch 사이트에서 예외의 형식이 결정됩니다. 그러나 C++ 예외를 사용하는 경우 예외의 형식은 throw된 예외 개체의 형식에 따라 throw 사이트에서 항상 결정됩니다. 이로 인해 throw된 개체에 대한 포인터의 형식이 throw된 개체의 형식과 다른 드문 경우에서 비호환성이 발생합니다.
다음 예제에서는 MFC 버전 3.0과 이전 버전 간의 이러한 차이의 결과를 보여 줍니다.
TRY
{
THROW((CException*) new CCustomException());
}
CATCH(CCustomException, e)
{
TRACE("MFC 2.x will land here\n");
}
AND_CATCH(CException, e)
{
TRACE("MFC 3.0 will land here\n");
}
END_CATCH
컨트롤이 항상 일치하는 예외 선언을 사용하여 첫 번째 catch
블록에 전달되므로 이 코드는 버전 3.0에서 다르게 동작합니다. throw 식의 결과
THROW((CException*) new CCustomException());
는 으로 생성되더라도 a CException*
로 CCustomException
throw됩니다. MFC 버전 2.5 이하의 CATCH 매크로는 런타임에 형식을 테스트하는 데 사용합니다CObject::IsKindOf
. 식이기 때문입니다.
e->IsKindOf(RUNTIME_CLASS(CException));
는 true이고, 첫 번째 catch 블록은 예외를 catch합니다. C++ 예외를 사용하여 많은 예외 처리 매크로를 구현하는 버전 3.0에서는 두 번째 catch 블록이 throw된 CException
매크로와 일치합니다.
이와 같은 코드는 일반적이지 않습니다. 일반적으로 예외 개체가 제네릭 CException*
을 허용하는 다른 함수에 전달되고 , "사전 throw" 처리를 수행하고, 마지막으로 예외를 throw할 때 나타납니다.
이 문제를 해결하려면 함수에서 호출 코드로 throw 식을 이동하고 예외가 생성될 때 컴파일러에 알려진 실제 형식의 예외를 throw합니다.
예외 다시 throw
catch 블록은 catch된 것과 동일한 예외 포인터를 throw할 수 없습니다.
예를 들어 이 코드는 이전 버전에서 유효했지만 버전 3.0에서는 예기치 않은 결과가 발생합니다.
TRY
{
// Do something to throw an exception.
AfxThrowUserException();
}
CATCH(CException, e)
{
THROW(e); // Wrong. Use THROW_LAST() instead
}
END_CATCH
}
catch 블록에서 THROW를 사용하면 포인터 e
가 삭제되므로 외부 catch 사이트에서 잘못된 포인터를 받게 됩니다. THROW_LAST 사용하여 다시 throwe
합니다.
자세한 내용은 예외: 예외 Catch 및 삭제를 참조 하세요.