일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Flutter
- Unity
- Data Structure
- c# 추상 클래스
- 구조체
- 도커
- docker
- 포인터
- 플러터
- github
- C# delegate
- 깃
- c# winform
- C언어 포인터
- c언어
- dart 언어
- C++
- gitlab
- vim
- Houdini
- HTML
- 다트 언어
- Python
- git
- c#
- jupyter
- c# 윈폼
- 유니티
- jupyter lab
- Algorithm
- Today
- Total
nomad-programmer
[Programming/C++] 예외 처리 생략과 실패 대응 본문
프로그래밍은 예측불허의 여정이다. 코드가 실행되는 동안 예외 상황은 피할 수 없고, 심지어 예외 처리 메커니즘도 때로는 예외를 처리하지 못할 수 있다. noexcept와 set_terminate를 활용해 예외 처리와 예외 처리 실패에 대응하고 프로그램의 안정성과 신뢰성을 높이는 방법을 알아보자.
예외 처리 생략 - noexcept
함수에서 문제가 발생할 때 반드시 예외를 발생시켜야 하는 것은 아니다. 때로는 예외를 발생시키는 것이 득보다 실이 더 클 때도 있다.오류와 예외는 엄연히 다르다. 값이나 실행 흐름을 충분히 예측할 수 있을 때는 if문으로 처리하는 것이 성능 면에서 훨씬 이득이다.
함수가 예외를 던지지 않음을 나타낼 때는 다음처럼 noexcept 키워드로 명시할 수 있다. 이처럼 함수가 예외를 던지지 않음을 명시하면 컴파일러가 코드를 최적화하고 빠르게 실행하는 데에 도움이 된다.
int func() noexcept
또는 다음처럼 함수를 호출할 때 noexcept 키워드를 사용할 수도 있다. 그러면 컴파일할 때 해당 함수가 예외를 던지는지 확인해 true나 false로 알려 준다.
bool does_not_throw = noexept(my_function());
참고로 함수에 noexcept 키워드를 붙였다고 해서 예외를 던지지 못하는 것은 아니다. noexcpet가 명시된 함수에서 예외를 던지면 어떻게 되는지 살펴보자.
#include <iostream>
using namespace std;
void real_noexcept() noexcept
{
cout<<"real_noexcept"<<endl;
}
// noexcept로 명시된 함수 안에서 예외 발생
void fake_noexcept() noexcept
{
cout<<"fake_noexcept"<<endl;
throw 1;
}
int main() {
real_noexcept();
try
{
fake_noexcept();
}
catch(int exec)
{
cout<<"catch "<<exec<<endl;
}
return 0;
}
// 결과
libc++abi: terminating due to uncaught exception of type int
real_noexcept
fake_noexcept
Process finished with exit code 134 (interrupted by signal 6:SIGABRT)
이 코드를 컴파일하면 경고는 발생하지만, 실행 파일은 만들어진다. 컴파일러는 noexcept 키워드가 붙은 함수는 예외를 던지지 않을 것으로 간주하고 그래도 컴파일한다. 하지만 실행해 보면 런타임 오류 메시지가 발생하며 프로그램은 강제로 종료된다.
예외 처리 실패 대응 - set_terminate
throw문으로 예외를 던졌는데 해당 예외를 받을 catch 문이 아예 없거나 있어도 형식이 맞지 않으면 프로그램은 강제로 종료된다. 이때 종료 처리 함수를 설정하는 set_terminate로 프로그램이 강제 종료되기 전에 특정 동작을 수행하도록 구성할 수 있다.
set_terminate(종료_처리_함수);
set_terminate로 종료 처리 함수를 지정하여 예외 처리 실패에 대응하는 예를 살펴보자.
#include <iostream>
#include <cstdlib>
using namespace std;
// 종료 처리 함수
void MyTerminate()
{
cout<<"MyTerminate called!" <<endl;
// 프로그램을 비정상으로 종료
exit(-1);
}
int main() {
set_terminate(MyTerminate);
throw 1; // 예외 발생
return 0; // 이 코드는 실행되지 않음
}
// 결과
MyTerminate called!
Process finished with exit code 255
main 함수에서 throw 1 코드를 만나면 catch 문을 찾을 수 없어 오류가 발생하고 프로그램이 강제로 종료된다. 그런데 강제로 종료하기 전에 ㄴet_terminate로 지정한 종료 처리 함수가 호출된다.
종료 처리 함수로 지정한 MyTerminate에서는 프로그램을 강제로 종료하는 exit 함수를 사용했다. exit 함수는 <cstdlib> 헤더에 정의되어 있다. exit 함수에 상태 코드로 0을 전달하면 프로그램을 정상으로, -1을 전달하면 비정상으로 종료한다. 이 상태 코드에 따라 내부에 정의된 각종 정리 작업을 수행한다.
비슷한 함수로 abortrㅏ 있는데 이 함수는 어떤 정리 작업도 수행하지 않은 채 프로그램을 비정상으로 즉시 종료한다.
'Programming > C++' 카테고리의 다른 글
[Programming/C++] 사용자 정의 리터럴 (0) | 2024.09.09 |
---|---|
[Programming/C++] vcpkg (0) | 2024.08.05 |
[Programming/C++] 연산자 오버로딩의 대한 예제 (0) | 2023.06.14 |
[Programming/C++] 함수 포인터의 변형 (함수 포인터 배열 관련) (0) | 2023.03.02 |
[Programming/C++] 다중 재귀 호출 (aka. Divide-And-Conquer) (0) | 2023.03.01 |