[배열] 디버깅

·

2 min read

[배열] 디버깅

우리가 소스코드를 작성하다보면, 때때로 우리 의도와는 다른 오류나 결과를 맞닥뜨리게 된다. 이를 “버그”라고 하는데, 버그를 효과적으로 찾고 해결하는 방법에 대해 알아 보자.

버그와 디버깅

버그(bug)는 코드에 들어있는 오류로, 버그로 인해 프로그램의 실행에 실패하거나 프로그래머가 원하는 대로 동작하지 않게 된다.

디버깅(debugging)은 코드에 있는 버그를 식별하고 고치는 과정으로, 프로그래머는 디버거라고 불리는 프로그램을 사용하여 디버깅을 하게 된다.

디버깅의 기본

프로그램은 인간보다 빠르게 연산을 수행하기 때문에, 프로그램을 실행시켜보는 것만으로는 오류를 찾기 어렵다. 이를 해결하기 위해 디버거를 사용한다.

디버거는 프로그램을 특정 행에서 멈출 수 있게 해주며, 멈춰있는 지점을 중지점이라고 한다. 중지점에서 프로그램이 멈춘 후, 프로그래머는 무슨 일이 일어나는지 확인할 수 있다. 또한, 디버거는 프로그램을 한 줄씩 실행할 수 있게 해주어, 프로그램의 결정을 단계별로 따라갈 수 있고, 이를 통해 프로그래머는 버그를 찾고 수정할 수 있다.

help50

아래의 코드를 컴파일하고 실행한다고 생각해보자.

int main(void)
{
    printf("hello, world\n");
}

make 프로그램을 이용하여 컴파일해보면 “implicitly declaring library function 'printf'” 이라는 에러 메시지가 나타난다.

이런 에러 메시지를 이해하기 힘들다면, help50 프로그램을 사용할 수 있다.

아래와 같이 make 앞에 help50 을 붙여서 실행하면 다시 컴파일시 생기는 오류를 해석해준다.

help50 make 파일이름

문제의 원인은 printf 함수를 사용하기 위해서 stdio.h 라이브러리를 포함해야 한다는 것이었다.

printf

하지만 이렇게 프로그램을 사용해서 해결할 수 없는 문제도 있다.

아래의 코드는 #을 10개 출력하기 위해 작성한 것이다.

#include <stdio.h>

int main(void)
{
    for (int i = 0; i <= 10; i++)
    {
        printf("#\n");
    }
}

이 코드를 컴파일 하고 실행해보면 에러는 발생하지 않지만, 우리 의도와는 다르게 #이 11개나 출력되는 것을 확인할 수 있다.

이럴 때에는, 직접 의심이 가는 변수를 출력해서 확인해 볼 수 있다.

#include <stdio.h>

int main(void)
{
    for (int i = 0; i <= 10; i++)
    {
        printf("i is now %i: ", i);
        printf("#\n");
    }
}

변수 i를 출력해보면, i가 0에서 시작하기 때문에 for 루프의 i <= 10 이라는 조건은 실제로 11번 만족한다는 사실을 알 수 있다.

따라서 이를 i < 10 으로 수정해주면 의도대로 #이 10번 출력될 것이다.

debug50

CS50 IDE를 사용하면 debug50이라는 프로그램을 사용할 수 있다.

아래와 같이 소스 코드에 직접 브레이크포인트를 지정하고 소스파일을 컴파일한 후에 debug50 파일명 으로 실행하면, 오른쪽 패널을 통해 변수의 값을 확인하거나 브레이크포인트부터 한 줄씩 코드를 실행해 볼 수 있다.


생각해보기

디버깅을 도와주는 프로그램은 어떤 경우에 더 큰 도움이 될까? 만약, 이런 프로그램의 도움 없이 직접 디버깅을 해야 한다면 어떻게 코드를 작성하는 것이 좋을까?

정답

디버깅 도구는 복잡한 코드와 런타임 에러 해결에 유용하다. 도구 없이 디버깅할 때는 모듈화, 로깅, 단위 테스트를 활용하여 코드를 체계적으로 관리하는 것이 중요하며, 이를 통해 코드의 가독성과 유지보수성을 향상시키고, 디버깅 오류를 줄일 수 있다.