Effective Debugging/Chatper 4. 디버거 활용법

created : 2020-04-07T11:44:40+00:00
modified : 2020-09-26T14:27:54+00:00

Item 28. 디버깅 버전으로 컴파일 하기

기억할 사항

Item 29. 한 단계씩 코드 실행하기

Item 30. 코드와 데이터 중단점 활용하기

Item 31. 리버스 디버깅

리버스 디버깅하는 방법

  1. break main을 사용해서 (또는 다른 breakpoint 를 걸어서) 리버스 디버깅할 곳에서 정지한다.
  2. record 를 사용해서 원하는 부분부터 기록한다.
  3. 실행하다가 거꾸로 가고싶으면 reverse-next 를 사용해서 거꾸로 올라간다.
  4. reverse-continue를 사용하면 거꾸로 올라가서 처음 나오는 breakpoint에 멈춘다.
    • 주의할 점. 데이터베이스에서 삭제하는 연산이나 시그널, 네트워크 패킷과 같이 비동기적 이벤트에서는 돌릴수 없다.

Item 32. 루틴 사이의 호출 흐름 추적하기

콜 스택에 쌓이는 정보

스택 트레이스

기억할 사항

Item 33. 변수와 표현식의 값을 분석하여 에러 찾기

기억할 사항

Item 34. 실행 중인 프로세스에 디버거 연동하기

Item 35. 코어 덤프 다루기

  1. 프로그램에서 메모리 덤프를 생성할 때 관련된 메타데이터도 함께 생성하도록 설정한다. 메모리 덤프를 생성하도록 설정하는 방법에 대해서는 앞에서 소개한 바 있다. 메타데이터를 생성할 때 최소한 프로그램의 버전 정보를 표시한다. 그 밖에도 프로그램을 실행하는 환경에 대한 데이터(프로세서, 운영체제, 환경변수, 공유 라이브러리 버전 등), 로그 파일, 사용자 입력, 프로그램 사용에 대한 히스토리 파일 등도 표기하면 디버깅에 도움이 된다.
  2. 프로그램에서 생성한 메모리 덤프 파일이 제대로 전달되도록 설정한다. 충돌이 발생한 후에 프로그램의 상태가 꼬였다면 외부 프로그램을 통해 전달하는 것이 좋다. 디버깅하려는 프로그램을 다른 프로그램으로 실행시킨 뒤, 그 프로그램에서 디버깅할 프로그램의 종료 상태를 확인해서 지정한 값과 일치할 때만 메모리 파일을 전달하도록 설정한다. 유닉스라면 프로그램이 SIGABRT 핸들러를 통해 앞서 지정한 값으로 종료하게 하고, 윈도우라면 예외 필터 함수를 통해 종료하게 한다. 데이터를 보낼 때는 HTTP POST 요청을 활용하는 것이 가장 쉬우면서도 안정적인 방법이다.
  3. 이렇게 전달되 데이터를 저장해서 나중에 분석할 때 활용하도록 디버깅 작업을 수행하는 환경에 HTTP 요청을 받아서 데이터를 저장하는 기능을 수행하는 서버를 간단히 작성한다. 나중에 분석하기 좋도록 메타데이터를 데이터베이스에 저장하는 것도 좋은 방법이다.
  4. 충돌이 발생한 프로긂의 버전을 구분하는 방법도 확보한다. 버전 관리 시스템에서 소스 코드의 각 버전마다 태그르 달고, 메타데이터에 이 태그도 함께 담아서 보낸다. 태깅된 소스 코드로부터 완전히 동일한 버전의 바이너리를 재현할 수 없다면 바이너리 실행파일을 각 버전마다 저장해두는 것이 좋다.
  5. 사용자가 겪은 문제를 디버깅할 때는 정상적인 소스 코드와 실행 파일과 충돌 시 생성된 메모리 덤프 파일을 디버거에 전달하여 구동한다.

기억할 사항

Item 36. 디버깅 도구 조율하기

Item 37. 어셈블리 코드와 메모리 값 확인하기