Objective-C gdb로 디버깅 하기

Objective-C를 debug할 때 다음과 같이 break point(이하 bp)를 지정할 수 있습니다.

b -[UIViewController setInterfaceOrientation:]

이렇게 지정한 뒤 실행하면 다음과 같이 중지됩니다.

Pending breakpoint 1 - "-[UIViewController setInterfaceOrientation:]" resolved
(gdb)


bt 명령을 이용하면 call stack를 볼 수 있습니다.

#0  0x3097263a in -[UIViewController setInterfaceOrientation:] ()
#1  0x30978386 in -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] ()
#2  0x309221fb in -[UIView(Internal) _didMoveFromWindow:toWindow:] ()
#3  0x30920883 in -[UIView(Hierarchy) _postMovedFromSuperview:] ()
#4  0x3092079e in -[UIView(Internal) _addSubview:positioned:relativeTo:] ()
#5  0x3091a113 in -[UIView(Hierarchy) addSubview:] ()
.........
(gdb)


#0은 현재 bp 된 위치를 나타내며, bp를 걸었던 UIViewController setInterfaceOrientation: 에서 멈춰있는 것을 볼 수 있습니다.
보통 call stack은 main()부터 시작하며, #<번호> 부분으로 이동하기 위해서는 frame 명령어를 사용합니다. 예를 들어 "#1 -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]" 부분으로 이동하기 위해서는 "frame 1"과 같이 입력합니다. 또는, 현재 위치를 기준으로 +1 되어 있으므로 "up 1"를 입력하여도 됩니다.

"frame 1"로 입력하였을 경우 다음과 같이 현재 위치가 변경됩니다.

(gdb) frame 1
#1  0x30978386 in -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] ()
(gdb)


이 상태에서 인자를 보고 싶을 때 일반 c application은 인자들이 목록에 나와서 display 명령어로 볼 수 있습니다.
이 때 주의할 점은 $ebp레지스터를 이용하기 때문에, 다른 frame의 값은 볼 수 없다는 것 입니다.

(gdb) frame 0
#0  0x3097263a in -[UIViewController setInterfaceOrientation:] ()
(gdb) display *(int *)($ebp + 16)
1: *(int *) ($ebp + 16) = 1
(gdb)


위와 같이 0 frame으로 변경한 뒤, setInterfaceOrientation:의 첫번째 인자를 보면 1로 표시됩니다.
$ebp는 함수 시작 시 설정되는($esp가 저장되어) stack의 시작 주소 이기 때문에 (int *)로 캐스팅 한 뒤 역참조 연산자인 *를 붙여서 정수 값을 출력 하였습니다.
 
일반 c 프로그램을 디버깅 할 때는 display가 유용하지만 Objective-C에서는 다른 방법으로 봐야 합니다. (display로 봐도 되긴 합니다)

(gdb) po _rootView
<UIView: 0xd1a650; frame = (0 0; 320 480); layer = <CALayer: 0xd1a680>>
(gdb)


display를 이용하면 다음과 같이 나옵니다.
(gdb) display _rootView
1: self->_rootView = (UIView *) 0xd1a650
(gdb) display *_rootView
2: *self->_rootView = {
  <UIResponder> = {
    <NSObject> = {
      isa = 0x31a5c620
    }, <No data fields>}, 
  members of UIView: 
  _layer = 0xd1a680, 
  _tapInfo = 0x0, 
  _gestureInfo = 0x0, 
  _gestureRecognizers = 0x0, 
  _charge = 0, 
  _tag = 0, 
  _viewFlags = {
    userInteractionDisabled = 0, 
    implementsDrawRect = 0, 
    implementsDidScroll = 0, 
    implementsMouseTracking = 0, 
    hasBackgroundColor = 0, 
    isOpaque = 1, 
    becomeFirstResponderWhenCapable = 0, 
    interceptMouseEvent = 0, 
    deallocating = 0, 
    debugFlash = 0, 
    debugSkippedSetNeedsDisplay = 0, 
    debugScheduledDisplayIsRequired = 0, 
    isInAWindow = 0, 
    isAncestorOfFirstResponder = 0, 
    dontAutoresizeSubviews = 0, 
    autoresizeMask = 0, 
    patternBackground = 0, 
    fixedBackgroundPattern = 0, 
    dontAnimate = 0, 
    superLayerIsView = 0, 
    layerKitPatternDrawing = 0, 
    multipleTouchEnabled = 0, 
    exclusiveTouch = 0, 
    hasViewController = 0, 
    needsDidAppearOrDisappear = 0, 
    gesturesEnabled = 1, 
    capturesDescendantTouches = 1, 
    deliversTouchesForGesturesToSuperview = 1, 
    chargeEnabled = 0, 
    skipsSubviewEnumeration = 0
  }
}
(gdb)


무엇인가 po가 더 간단해보이죠??? (장, 단점이 있습니다)

디버깅을 Xcode가 다 해준다지만.. 그래도 gdb 정도는 쓸 수 있어야겠죠???
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/06/11 12:55 2009/06/11 12:55
, ,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/229


블로그 이미지

빗소리를 먹는 사람.

- 장현준

Notices

Archives

Authors

  1. 장현준

Recent Trackbacks

  1. 듀얼클러치의 생각 rsvin28's me2DAY 2009

Calendar

«   2012/02   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      

Site Stats

Total hits:
158001
Today:
71
Yesterday:
228