F.R.I.D.A.Y.

코드 디버깅 with Visual Studio 본문

DEV/Tip

코드 디버깅 with Visual Studio

F.R.I.D.A.Y. 2021. 10. 12. 14:53
반응형

 개발의 한 축, 디버깅


시작하며

 개발에선 코드를 잘 작성하는 것이 중요합니다. 알고리즘과 더불어 코드 구조를 어떻게 짜느냐도 큰 부분을 담당하죠. 그러나 코드를 짜는 것에 있어, 항상 원하는 결과를 생성하지는 않습니다. 컴파일러단에서 오류가 발생[# 이를 신택스 에러(Syntax error)라 합니다.]하기도 하지만, 런타임 에러나 시맨틱 에러[# 문법상 문제는 없지만 의도하지 않은 결과가 일어나는 것, 그것을 시맨틱 에러(semantic error)라 부릅니다.]가 일어나기도 합니다.

 

 이와 같은 버그를 해결하는 것을 우리는 디버깅이라 부릅니다. 요즘은 디버깅 능력을 보조하는 여러 툴이 있지만, 오늘은 IDE로 Visual Studio를 사용하는 이들에게 도움이 되는 글을 가져옵니다.

 

 

디버깅

 Visual Studio에서는 빌드[# 소스코드에서 실행파일로 변환하는 일련의 과정]를 하고 곧바로 디버깅 모드로 실행하는 방법[# 단축키 F5]이 있는가 하면, 디버깅과 프로그램의 실행을 구분 지어 실행하는 방법[# 빌드: Ctrl + Shift + B\n실행: Ctrl + F5]이 있기도 합니다.

 

 이제부터 Visual Studio에서 제공하는 디버깅에 도움이 되는 기능을 하나씩 살펴봅니다.

 

중단점

 소스코드 좌측 끝을 보면, 빨갛게 칠해진 동그라미가 그려질 때가 있습니다. 이렇게 빨간 동그라미가 입력된 곳이 중단점(break point)이 설정된 곳입니다.

LINE 292, LINE 296에 중단점이 설정된 모습

 프로그램을 디버깅 모드로 실행했을 때, 실행 순서에 맞게 코드를 실행하다 중단점을 만나게 되면, 프로그램의 실행이 일시 중지되고 현재 중지된 시점의 프로그램 상태[# 현재 실행 지역의 변수 값 등]를 확인할 수 있습니다.

LINE 293 적용된 중단점으로 실행이 멈춘 상태. 다음 실행할 코드를 노란색 화살표로 표시해준다.

 중단점에 걸리게 되면 노란 화살표로 다음 실행할 코드를 확인할 수 있으며, 변수의 값을 확인할 수 있는 창도 볼 수 있습니다.[# 변수의 값을 확인할 수 있는 창은 중단점에 걸리지 않더라도 확인 가능합니다]

 

# 변수 값을 확인할 수 있는 <변수 상태창>은 다음에서 안내합니다.

 

중단점 설정

 중단점은 위 이미지와 같이 빨간 동그라미 부분이 표시된 부분을 마우스로 클릭하거나, 중단점을 설정하고 싶은 부분의 코드 라인에서 캐럿(텍스트 커서, 키보드 커서)을 둔 상태로 F9 단축키를 이용해서도 설정할 수 있습니다.

 반대로 해제할 때는 중단점이 설정된 부분을 클릭하거나 동일하게 F9를 이용해 해제할 수 있습니다.

 

 또한, 중단점을 조건부로 실행할 수도 있습니다. 다음 코드에서, cursor가 nullptr(NULL)인 경우에만 중단점에 걸리도록 하고 싶다면 <조건부 중단점>을 설정하면 됩니다.

void bag::show_contents(const char* desc) const
{
	dnode* cursor = head_ptr;
	std::cout << "============= show content " << (desc ? desc : "\b") << " =============" << std::endl;
	if (!cursor) std::cout << "No data" << std::endl;
	for (int i = 0; cursor; cursor = cursor->link_foreward(), ++i) {
		std::cout << std::setw(3) << i << ": " << cursor->data() << std::endl;
	}

	std::cout << std::endl;
}

 

 

조건부 중단점

 중단점 표시(빨간 동그라미) 위에 마우스 커서를 올려놓으면 이미지와 같이 두 가지 옵션이 나옵니다. 그중, 톱니바퀴 모양의 아이콘을 클릭하면 아래의 [중단점 설정]이 코드 뷰에 나타나게 됩니다.

중단점 설정을 열었을 때 초기 모습(좌)과 모두 활성화했을 때 모습(우)

  • 조건
    - 조건[# 단순 조건식이나 조건식을 몇 번이나 만족했는지 등]을 만족하는 경우 중단점이 실행되어 프로그램의 실행이 일시 중지됩니다.
  • 작업
    - 해당 지점이 되면 출력 창에 현재 변수의 값을 출력할 수 있습니다. 코드 실행 계속 옵션으로 출력만 할 것인지, 일시 중지도 할 것인지 선택할 수 있습니다.

 

 조건부 중단점은 반복문에서 그 진가를 발휘합니다. 열 번, 스무 번이 아니라 1,000번, 혹은 그 이상의 반복에서 중간에 문제가 생길 때, 반복문 안에 단순 중단점을 설정하면 첫 반복에서부터 걸립니다. 따라서 조건부 중단점으로 오류가 나기 수 번 전 반복에서 중단이 일어날 수 있도록 해주는 점에서 꼭 필요한 존재입니다.

 

중단 상태에서 코드 실행

 간단한 오류의 경우에는 변수의 상태를 확인하는 것으로 문제를 해결하는 실마리를 찾을 수 있습니다. 더 이상 중단점이 필요하지 않다고 생각이 되면, F5를 이용해 한줄한줄 실행하지 않고 연속적으로 실행하도록 할 수도 있죠.

 

 그러나 간단한 오류만 나오는 것은 아닙니다. 그럴 때는, 오류가 일어나기 수 라인 전에 중단점을 설정해 변수 상태와 각종 정보를 확인해가면서 라인 바이 라인으로 진행해야 합니다.

 

 그럴 때 필요한 것이 F10과 F11입니다. F10은 프로시저 단위 실행이라 불려서 실행할 구문이 함수라면 해당 함수를 실행한 결과만 보는 것이고, F11은 한 단계씩 실행은 함수를 만났을 때 해당 함수 안으로 들어가는 방식으로 처리됩니다.

단축키 말고도 버튼 클릭으로도 할 수 있습니다.

 

 코드로 예시를 들어보겠습니다.

	for (size_t i = 0; i < size() && pivot; pivot = pivot->link_foreward()) {
		min = pivot;
		temp = pivot->link_foreward(); // break point
		while (temp) {
			if (temp->data() < min->data()) min = temp;
			temp = temp->link_foreward();
		}
		dnode::value_type tData = pivot->data();
		pivot->set_data(min->data());
		min->set_data(tData);
	}

위 코드에서 break point로 설정된 부분에서 F10(프로시저 단위 실행)과 F11(한 단계씩 실행)은 서로 다른 작업을 합니다.

 

  • F10을 누른다.
    pivot->link_foreward() 함수가 실행된 반환값이 temp에 저장됩니다.
  • F11을 누른다.
    pivot->link_foreward() 함수로 진입합니다.

F10을 누르기 전(좌)과 후(우)의 temp 변수 상태. 값이 바뀌었다.
F11을 누른 모습. 프로그램이 link_foreward로 진입했다.

 

 F10과 F11은 상황에 맞게 적재적소에 사용하기 바랍니다. 모든 중단점을 해제할 때는 Ctrl + Shift + F9를 누르면 됩니다. 그러면 중단점을 해제할 것인지 묻는 창인 나옵니다.

 

변수 상태창

 디버깅이 실행중일 때 일반적으로 좌측 하단을 보면 [자동, 로컬, 조사식1]이라불리는 탭이 존재합니다.

 현재 프로그램에서 사용중인 변수와 그 값을 확인할 수 있습니다. 세 옵션은 제각기 다른 의미를 가집니다. 로컬과 자동은 툴에서 제어하는데 반해서 조사식의 경우 개발자가 원하는 변수를 계속 추적할 수 있도록 조사식을 만들 수 있습니다.

int arr[10] = {0, };

for(int i = 0 ; i< 10; ++i){
	arr[i] = 10 * i;
}

 위와 같음 코드가 있을 때, 자동과 로컬에서는 arr의 값만 보이지만[# arr[i]의 값은 바로 보이지 않습니다] 조사식에서는 조사식 arr[i]로 설정하면 i에 따른 arr의 값을 확인할 수 있습니다.

 

 

호출 스택

 몇몇 오류는 쉽게 잡아내지만, 대개 실행중 일어나는 런타임 에러는 호출 스택을 함께 확인해야 합니다.

 예시로 설명하는 null pointer exception의 경우 어디에서 오류가 났는지 확인하기 어렵습니다. 이럴 때는 호출 스택을 이용합니다.

 

 호출 스택은 디버그 모드에서 우측 하단 탭에 존재합니다.

IDE 우측 하단 호출 스택

 호출 스택의 각 부분을 클릭해 어디에서 어떤 함수를 호출해서 이렇게 오류 코드까지 오게 되었는지를 확인할 수 있습니다. 이 경우, list_head_insert 함수에서 오류가 나네요.

 설명하기 위해 주석 처리한 if (backup) 부분이 nullptr 분기를 해주지 않아서 발생하는 문제로 해당 부분의 주석을 해제하면 다시 정상적으로 실행이 됩니다.

 


함께보기.

 

예외처리 - assert 사용해보기

 많은 프로그래머들이 작성된 코드로 인해 발생하는 각종 문제들에 골머리를 앓고 있습니다. 현업 개발자뿐만 아니라 일반 학부생, 아마추어 개발자들도 예외는 아닌데요, 오늘 포스팅에서는

pang2h.tistory.com

 

다들 디버깅 열심히 하세요

 

# index

728x90
반응형
Comments