맥을 쓰면 기본적으로 lldb라는 디버거가 설치되어있다. 나도 피씬 때 처음 써봤는데 익숙해지면 정말 좋다. 피씬 시험볼 때도 애용한 편.. 나는 시간이 지나면서 사람들이 디버거를 사용할 거라고 생각했는데, 그렇지 않았다. 그러니 내가 홍보해야지. 이 글은 lldb의 매우 기본적인 기능을 다룬다. 글 맨 아래 링크의 글에 더 많은 기능이 소개되어있다!
컴파일 옵션
우선 디버깅을 하려면 컴파일 할 때 -g 옵션을 줘야한다.
gcc -g main.c
g++ -g main.c
이런 식으로. 그래야 디버깅을 할 때 코드를 볼 수 있다. 안 그러면 어셈블리로 디버깅하는 끔찍한 일이 벌어진다. 사실 끔찍하진 않다. 나는 좋아한다.
코드 보기
# 특정 함수 코드 보기
list main
# 특정 파일 코드 보기
list main.c
실행
# 길게 쓰면 run
run
# 짧게 쓰면 r
r
# argument를 넘길 수도 있다
# 이렇게 하면 argv[1]에 "hyeyoo"가 들어간다.
run "hyeyoo"
# 그런데 가끔 run 뒤에 argument를 넘기는 게 안될 때도 있다.
# 이유는 모른다. 안 되는 컴퓨터가 종종 있다. 그럴 땐
settings set target.run-args "hyeyoo"
그런데 그냥 실행하면 프로그램이 종료될 때까지 실행된다. 디버깅은 버그를 찾아낼 때 사용하는 건데, 프로그램이 끝날 때 까지 실행해버리면 내가 보고 싶은 코드가 어떻게 돌아가는지 볼 수 없다. 이럴 때 breakpoint를 사용하면 원하는 위치에서 프로그램을 멈추게 할 수 있다.
breakpoint
breakpoint는 기본적으로 실행시 어떤 코드에서 멈출지 정하는 용도로 사용한다. 예를 들어 memoryLeak()를 디버깅하려면 memoryLeak()이라는 함수에 breakpoint를 걸고 run을 하면 된다. 그럼 프로그램이 돌다가 memoryLeak 함수를 만나면 멈춘다. 아니면 함수 말고 소스코드의 n번째 줄에 걸 수도 있다.
# breakpoint main함수에 걸기
b main
# main.c의 7번째 라인에 걸기
list main.c
b 7
# main.c의 7번째 라인에 걸기
b main.c:7
# breakpoint 제거
br del (breakpoint 번호)
# 모든 breakpoint 제거
br del
next (n), step
breakpoint를 걸어서 멈추면, 코드를 한줄 씩 실행할 수 있는데 그게 next, step 명령어다. 차이점은
next : step over - 한 줄을 실행하되, 함수가 있다면 함수 안으로 들어가지 않는다.
step : step into - 한 줄을 실행하되, 함수가 있다면 함수 안으로 들어간다.
continue (conti), finish
그런데 한 줄씩 실행하는 건 좀 노가다일 때가 있다. (반복문 빠져나올 때...) 그래서 다음 breakpoint까지 쭉 실행하려면 continue를 하면 되고, 함수를 빠져나오려면 finish를 하면 된다.
print (p)
print는 변수의 값을 출력하는 명령어다. 사용법은 정말 간단하다.
# 변수 값 출력
print ptr
# 포인터 연산, 구조체 관련 연산도 가능하다. p는 print 줄인 것
p ptr
p *ptr
p ptr->next
# 형변환도 가능하다.
p (unsigned long long)ptr;
p (char)ptr;
memory leak 잡는 법
/* 주의 : 릭을 찾는 방법은 많다. 이건 그냥 내가 쓰는 방법이다. */
맥에는 leaks라고 실행중인 프로세스의 메모리 릭을 검사하는 도구가 있다. leaks (프로세스 id) 또는 leaks (실행파일 이름)을 실행하면 된다. 그래서 보통 leaks로 메모리 릭을 체크하려면 main문의 맨 마지막에 무한루프를 걸고, 프로그램을 실행시킨 후에 leaks로 검사한다.
lldb와 leaks를 사용하면 어디서 메모리 릭이 나는지 확인할 수 있다. 우선 lldb로 run을 하면 프로세스 id가 나오는데, 거기에 leaks를 실행하면 된다. 보통 나는 쉘을 2개 띄운 후, 한쪽에는 lldb를 실행하고, 나머지 한쪽에는 아래 명령어를 돌린다. (0.5초마다 leaks 돌리기)
while true; do leaks (lldb에 나온 프로세스 id); sleep 0.5; done
그럼 코드를 한 줄씩 실행하다 릭이 나오면 아래 사진처럼 나온다.
참고하면 좋을 자료들
다음에는 더 advanced한 기능들을 글로 소개해볼 생각이다.
아래 튜토리얼들에도 좋은 기능들이 소개되어있다!
aaronbloomfield.github.io/pdr/docs/lldb_summary.html
aaronbloomfield.github.io/pdr/tutorials/02-lldb/index.html
lldb.llvm.org/use/tutorial.html
'Life is 42' 카테고리의 다른 글
42의 동료 평가, 그리고 시행착오 (7) | 2020.10.28 |
---|
댓글