Short-circuit evaluation?
A && B나 A || 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++의 throw는 catch로 한 번에 점프하면서 심지어 적당한 처리까지 빼놓지 않습니다...
하지만 그런 컴파일러의 마법같은 최적화를 제외하면 대충 비슷하게 동작합니다