Search
Duplicate
🖲️

Short-circuit evaluation을 활용한 예외 처리

간단소개
throw, try/catch 따라하기
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
Scrap
태그
short-circuit evaluation
9 more properties

Short-circuit evaluation?

A && BA || B 등에서는 A의 결과에 따라 B가 평가되지 않을 수도 있습니다.
예를 들어 true || printf("Hello world!\n")printf는 실행되지 않습니다.
이런 것을 short-circuit evaluation이라고 합니다.

Exception, throw, try~catch

C++, Java 등 다양한 언어에서는 try , catch를 사용해 예외를 처리할 수 있습니다.
해당 예외에 대한 Exception 객체를 throw하면 가까운 catch에서 처리할 수 있습니다.
int doSomethingMayFail(int a, int b) { return a / b; // 예외가 발생할 수 있는 부분 } int doSomething(int a, int b) { try { return doSomethingMayFail(a, b); // 이 try 블록 안에서 예외가 발생하면 } catch(Exception e) { System.out.println("오류 발생!"); return 0; // 해당 예외에 대한 Exception을 catch에서 처리할 수 있음! } } void main() { System.out.println(doSomething(100, 0)); // 출력 결과는 0 }
Java
복사
Exception을 사용하는 예시
하지만 C에는 throw, try, catch나 그런 비슷한 게 없죠.

throw, try, catch를 따라해보자!

펼치면 자세한 내용을 확인할 수 있습니다.
별로... 알고싶지 않은 내용일 수 있어요. 벌써 코드가 개판이 됐네요

Short-circuit evaluation을 활용하자!

위의 예시에서는 예외가 발생한 경우 catch로 넘어갈 때 if를 사용했습니다.
예외가 발생할 수 있는 함수 여러개를 연달아 실행한다면... 대충 이렇게 될 거에요...
하지만 short-circuit evaluation을 활용한다면 정말 간단해집니다!
int do_something_with_multiple_throwable_functions(int base, int *out_result) { t_exception *exception; int seven; int fourteen; int twenty_one; int ft; if ( // 예외가 발생하면 다음으로 진행하지 않음! get_lucky_seven(base, &exception, &seven) || get_double(seven, &exception, &fourteen) || sum(seven, fourteen, &exception, &twenty_one) || get_double(twenty_one, &exception, &ft)) { // 한 번이라도 예외가 발생하면 여기에서 처리! ft_put_line_fd(d.value.exception, STDERR_FILENO); return (42); } return (ft); }
C
복사
short-circuit evaluation을 통해 코드를 획기적으로 줄인 모습
대신 이렇게 된다면 예외가 발생할 수 있는 부분의 코드를 조금 수정해야 합니다.
결과를 리턴하는 것이 아니라 성공이면 0, 예외가 발생하면 1을 리턴해야 합니다.
그리고 결과를 넣을 곳의 주소와 exception의 주소도 받아야 합니다.
t_err ft_malloc(size_t size, void **out, t_exception *exception) { void *const result = malloc(size); if (!result) { *exception = "OUT OF MEMORY!"; return (true); } *out = result; return (false); }
C
복사
exception을 사용하는 간단한 예시

Stack Trace를 추가하자

열심히 준비했으나, 순수 C로 할 만 한 짓은 아닌 것 같아서 지웠습니다.
개발 과정 중에는 그냥 디버거 쓰면 디버거가 알아서 이것보다 훨씬 더 잘 해 줍니다.
Error on main.c:5: Hello world! | test stacktrace: At main.c:12 Error on main.c:5: Hello world! | test stacktrace: At main.c:21 - test... | This is optional message, even multiline is OK also! | xD
Plain Text
복사

실제 C++의 throw랑 비교하면?

C++의 throw가 더 빠릅니다.
이 방식의 예외 처리는 함수를 하나하나 벗어나면서 자원 해제 등의 적당한 처리를 합니다.
C++의 throwcatch로 한 번에 점프하면서 심지어 적당한 처리까지 빼놓지 않습니다...
하지만 그런 컴파일러의 마법같은 최적화를 제외하면 대충 비슷하게 동작합니다