[Xcode] 디버깅 (debugging)

JJOOEE__·2024년 7월 1일

Xcode

목록 보기
3/3
post-thumbnail

🍎 디버그? 디버깅?

  • 버그 (bug) : 논리적 오류, 프로그래밍에서의 오류, 직접 찾아 수정해야함
  • 디버그 (debug) : 오류를 수정하는 과정
  • 디버깅 (debugging) : 코드에서 오류를 만났을 때, 프로그램의 잘못을 찾아내고 고치는 것

비슷하지만 다른 헷갈리는 용어 정리

  • 에러 (error) : 문법상 오류, 컴파일러가 잡아냄

🍎 디버깅이 중요한 이유

  1. 오류 및 버그 수정
  • 정상적인 동작 보장 : 소프트웨어가 의도한 대로 작동하도록 하여 사용자가 예상한 결과를 얻을 수 있게 함
  • 데이터 무결성 유지 : 오류가 발생하면 데이터가 손상되거나 유실될 가능성이 있는데, 디버깅을 통해 이러한 문제를 예방할 수 있음
  1. 보안 강화
  • 취약점 제거 : 코드의 버그로 인해 발생하는 많은 보안 문제를 디버깅을 통해 취약점을 조기에 발견하고 수정할 수 있음
  • 악용 방지 : 공격받을 수 있는 버그를 사전에 제거함으로써 소프트웨어를 더 안전하게 만들 수 있음
  1. 코드 품질 향상
  • 가독성 및 유지보수성 향상 : 디버깅을 통해 코드의 구조적 문제를 발견하고 개선이 가능, 이는 코드의 가독성과 유지보수성을 높이는 데 도움이 됨

🍎 디버깅 방법

🍏 1. 소스코드 에서 BreakPoint

  • class GameManage 에 BreakPoint를 걸어보겠음

  • BreakPoint를 걸어줄 코드가 위치한 줄의 번호를 1번 클릭하면 파란색으로 변하면서 BreakPoint가 걸림

  • 다시 한 번 숫자를 클릭하면 일시 비활성화가 됨
  • 영구삭제하려는 BreakPoint는 파란색 아이콘을 마우스로 드래그하여 코드 에디터 왼쪽 여백에서 이동시키면 브레이크 포인트가 제거됨

🌈 step over

  • 프로그램을 실행하면서 한 줄씩 코드를 실행
  • 일반적으로 차례차례 확인하기 위해 많이 사용
  • 현재 실행 중인 함수나 메소드의 내부 코드는 실행하지 않고 다음 줄로 넘어갑니다.
  • 주로 다음 줄로 넘어가면서 변수의 값이나 프로그램의 흐름을 확인할 때 사용

🌈 step into

  • breakpoint로 설정한 라인의 함수나 변수로 바로 넘어가게 만듬
  • 현재 실행 중인 함수나 메소드의 내부 코드로 들어가서 한 줄씩 실행
  • 함수나 메소드 호출 시 해당 함수나 메소드의 내부로 진입하여 디버깅 가능
  • 만약 함수나 메소드가 없는 줄에 커서가 위치하면 Step Over와 동일하게 다음 줄로 이동

🌈 step out

  • step into로 들어간 함수나 변수를 빠져나올 때 사용
  • 현재 실행 중인 함수나 메소드의 내부 코드를 빠져나와 호출된 곳으로 돌아감
  • 버그 중인 함수나 메소드의 모든 코드를 실행하지 않고 바로 호출된 지점으로 돌아갈 때 사용
  • 주로 깊게 중첩된 함수나 메소드를 디버깅 중에 빠져나올 때 유용

🍏 2. LLDB(Low-Level Debugger)

◻️ LLDB란 무엇인가?

  • Xcode의 내장 디버거로, 개발자가 코드 실행 중에 프로그램 상태를 조사하고 제어할 수 있는 강력한 도구

Xcode에서 LLDB 콘솔 활성화

  • APP을 실행하고 Breakpoint에 걸리거나 pause 시키면 콘솔에 lldb가 나타난다

◻️ LLDB 명령어 문법

(lldb) command [subcommand] -option "this is argument"
  예시: (lldb) breakpoint set --file test.c --line 12

argument는 공백이 포함되는 경우가 있어 ""로 묶어줄 수 있다

◻️ LLDB 명령어

🌈 help

  • 사용법을 출력한다
# 커맨드
(lldb) help breakpoint 
# 서브커맨드
(lldb) help breakpoint set

🌈 apropos

  • 원하는 기능의 명령어가 있는지 검색한다
(lldb) apropos "reference count"
[ 결과 ]
# The following commands may relate to 'reference count':
# refcount -- Inspect the reference count data for a Swift object

🌈po (Print Object)

  • 객체의 내용을 출력
  • 객체의 프로퍼티나 메소드 호출 결과를 확인하는 데 사용
(lldb) po someVariable

🌈 p (Print)

  • 표현식을 평가하고 결과를 출력
(lldb) p someVariable + 1

Breakpoint

🌈 특정 함수에 걸기

(lldb) breakpoint --name viewDidLoad
(lldb) br s -r '^hello`
(lldb) rb '^hello`

🌈 정규식을 따르는 모든 함수 모두에 걸기

(lldb) breakpoint set --func-regex '^hello`
(lldb) br -n viewDidLoad

🌈 File & line에 걸기

(lldb) br s --file ViewController.swift --line 20
(lldb) br s -f ViewController.swift --l 20

🌈 breakpoint에 조건 걸기

(lldb) breakpoint set --name "viewWillAppear" --condition animated
(lldb) br s -n "viewWillAppear" -c animated
animated가 true인 경우에만 break

🌈 break 시 원하는 lldb 커맨드 실행해주고 continue

(lldb) breakpoint set -n "viewDidLoad" --command "po $arg1" -G1
(lldb) br s -n "viewDidLoad" -C "po $arg1" -G1
"po $arg1" : 현재 함수의 1st Argument의 인스턴스 값 확인
G1 : 자동 continue
shorthand breakpoint

🌈 특정 함수에 걸기

(lldb) b viewDidLoad

🌈 현재 파일 + 특정 line에 걸기

(lldb) b 20

🌈 특정 파일 + 특정 line에 걸기

(lldb) b ViewController.swift:20

🌈 현재 파일의 특정 text를 포함한 line 모두에 걸기

(lldb) b /stop here/

🌈 특정 주소값에 걸기

(lldb) b 0x12345678

Breakpoint 리스트 확인하기

🌈 상세하게 전체 목록 출력

(lldb) breakpoint list
(lldb) br list

🌈 간단하게 출력

(lldb) br list -b

🌈 특정 id로 검색하여 출력

(lldb) br list <id>

breakpoint 삭제/비활성화 하기

🌈 모든 breakpoint 삭제

(lldb) breakpoint delete
(lldb) br de

🌈 특정 br 삭제

(lldb) br de <id>

🌈 모든 breakpoint 비활성화

(lldb) breakpoint disable
(lldb) br di

🌈 특정 br 비활성화

(lldb) br di <id>

Stepping

🌈 one step 이동

  • 코드 상 정말 한 줄을 이동한다
  • 다음 줄이 function call이면 해당 function의 첫 번째 줄에서 멈춘다
(lldb) step

🌈 step over 이동

  • 비슷하게 한 줄 이동이긴 하지만
  • 다음 줄이 function call이면 해당 function이 return될때까지 진행시킨 후 멈춘다
(lldb) next

🌈 현재 function 끝까지 이동

  • 현재 진행중인 함수가 return될때까지 프로그램을 진행시킨 후 멈춘다
(lldb) finish

Expression

🌈 오브젝트 읽기

  • "-O"옵션 : 읽으려는게 Object일때
(lldb) po <인스턴스명>
(lldb) expression -O --<인스턴스명>

변수 값 읽기 & 변경하기

🌈 레지스터로 불러오기

  • LLDB는 내부적으로 값이 출력될때마다 Local Variable을 레지스터($R~) 형태로 저장한다
  • 이 레지스터는 break context
(lldb) expression <인스턴스명>
(lldb) e <인스턴스명>

🌈 값 변경하기

(lldb) expression $R0!.backgroundColor = UIColor.blue

🌈 break 풀기

  • 방금 변경한 사항이 적용된채로 남은 코드가 진행된다
(lldb) continue

🌈 변수 할당하기

변수이름에 $를 붙혀줘야 한다
(lldb) expr var $view = UIView(frame: CGRect(x: 100, y:100, width: 80, height: 80))

🌈 Multi-line expression 사용하기

  • continue해보면 self.view에 subview가 추가된 것을 볼 수 있다
(lldb) expression
# Enter expressions, then terminate with an empty line to evaluate:

1 $view.backgroundColor = UIColor.blue
2 self.view.addSubview($view)

expression 중 만나는 breakpoint는 무시하기

🌈 Multi-line expression 사용하기

  • default는 true(무시)로 설정된다
(lldb) expression --ignore-breakpoints true --
(lldb) e -i 1 --

(lldb) expression --ignore-breakpoints false --
(lldb) e -i 0 --

주소값과 타입만으로 변수에 접근

  • 이를 위해 필요한 구체적인 동작은, 해당 주소에 있는 값을 적절한 타입으로 캐스팅하는 것이다

  • 이건 바로 가능한 부분은 아니고 UIKit 모듈의 unsafeBitCast( _, to: ) 함수를 활용해야 한다

🌈 UIKit모듈 import하기

(lldb) expr -l Swift -- import UIKit

🌈 캐스팅하기

(lldb) expr -l Swift -- var $<변수명> = unsafeBitCast(<주소값>, to: <타입명>.self)
(lldb) expr -l Swift -- var $myLabel = unsafeBitCast(0x7fdf7611, to: UILabel.self)
profile
개발이 어려운 나를 위한... 개발노트

0개의 댓글