디버거 란 무엇이며 문제를 진단하는 데 어떻게 도움이됩니까?


107

이것은 프로그램에 문제가 있지만 디버거를 사용하여 문제의 원인을 진단하는 방법을 모르는 새로운 프로그래머를 지원하기위한 범용 질문입니다.

이 질문은보다 구체적인 질문의 세 가지 클래스를 다룹니다.

  • 프로그램을 실행할 때 내가 제공 한 입력에 대해 예상 한 출력이 생성되지 않습니다.
  • 프로그램을 실행하면 충돌이 발생하고 스택 추적이 제공됩니다. 스택 추적조사 했지만 스택 추적이 충분한 정보를 제공하지 않기 때문에 여전히 문제의 원인을 모릅니다.
  • 프로그램을 실행할 때 세그먼트 오류 (SEGV)로 인해 충돌이 발생합니다.

3
하셨습니다. 디버깅 기술에 대한 관련 "이동"Q & A (예 : 디버거, 기타 디버그 도구 (예 : valgrind), 전략적 printfs, 스트레스 테스트, 분할 및 정복 등)를 사용하는 것도 좋습니다 .
Paul R

1
@PaulR에 동의합니다. FAQ에는 이와 같은 내용이 포함되어야합니다.
Nicu Stiurca 2014 년

답변:


73

디버거는 프로그램이 실행되는 동안 프로그램의 상태를 검사 할 수있는 프로그램입니다. 이를 수행하는 데 사용 하는 기술적 수단 은 디버거 사용 방법의 기본을 이해하는 데 중요하지 않습니다. 디버거를 사용하여 프로그램이 코드의 특정 위치에 도달하면 프로그램 실행을 중지 한 다음 프로그램의 변수 값을 검사 할 수 있습니다. 디버거를 사용하여 프로그램을 한 번에 한 줄씩 매우 느리게 실행할 수 있으며 ( 단일 스테핑 이라고 함 ) 해당 변수의 값을 검사 할 수 있습니다.

디버거 사용은 예상되는 기본 기술입니다.

디버거는 프로그램의 문제를 진단하는 데 도움이되는 매우 강력한 도구입니다. 그리고 모든 실용적인 프로그래밍 언어에 디버거를 사용할 수 있습니다. 따라서 디버거를 사용할 수 있다는 것은 전문가 나 열성적인 프로그래머 의 기본 기술 로 간주됩니다 . 디버거를 직접 사용하는 것은 다른 사람에게 도움을 요청하기 전에 스스로 해야하는 기본적인 작업 으로 간주됩니다 . 이 사이트는 헬프 데스크 나 멘토링 사이트가 아닌 전문 프로그래머를위한 것이므로 특정 프로그램의 문제에 대해 질문이 있지만 디버거를 사용하지 않은 경우 질문이 닫히고 반대 투표를받을 가능성이 큽니다. 이와 같은 질문을 계속하면 결국 더 많은 게시가 차단됩니다.

디버거가 당신을 도울 수있는 방법

디버거를 사용하여 변수에 잘못된 값이 있는지 여부와 프로그램에서 해당 값이 잘못된 값으로 변경된 위치를 확인할 수 있습니다.

단일 스테핑을 사용하면 제어 흐름이 예상대로인지 여부를 확인할 수도 있습니다. 예를 들어 if분기가 예상 할 때 실행되어야 하는지 여부 입니다.

디버거 사용에 대한 일반 참고 사항

디버거 사용의 세부 사항은 디버거와 사용중인 프로그래밍 언어에 따라 다릅니다.

  • 이미 프로그램을 실행중인 프로세스에 디버거를 연결할 수 있습니다 . 프로그램이 멈춘 경우 할 수 있습니다.

  • 실제로는 처음부터 디버거의 제어하에 프로그램을 실행하는 것이 더 쉽습니다.

  • 당신은 나타낼 경우 프로그램이 실행이 중지해야하는 라인의 소스 코드 파일과 줄 번호를 표시하여 실행을 중지해야한다, 또는으로 중지하려면 프로그램 (중지해야하는 방법 / 함수의 이름을 표시하여 실행이 메소드에 들어가 자마자). 기술적으로 디버거가 프로그램을 중지시키는 데 사용하는 것을 중단 점 이라고 하며이 프로세스를 중단 점 설정 이라고 합니다 .

  • 대부분의 최신 디버거는 IDE의 일부이며 중단 점 설정, 프로그램 실행 및 단일 스테핑을위한 포인트 앤 클릭 인터페이스와 함께 프로그램의 소스 코드 및 변수를 검사 할 수있는 편리한 GUI를 제공합니다.

  • 프로그램 실행 파일이나 바이트 코드 파일에 디버깅 기호 정보 와 소스 코드에 대한 상호 참조가 포함되어 있지 않으면 디버거를 사용하는 것이 매우 어려울 수 있습니다 . 정보가 있는지 확인하기 위해 프로그램을 약간 다르게 컴파일 (또는 재 컴파일) 해야 할 수 있습니다 . 컴파일러가 광범위한 최적화를 수행하면 이러한 상호 참조가 혼란 스러울 수 있습니다. 따라서 최적화를 해제 한 상태에서 프로그램다시 컴파일해야 할 수도 있습니다 .


4
이것은 가장 중요한 디버거를 놓치기 때문에 불완전합니다. Stackoverflow에 대한 질문 수를 매우 크게 줄일 수있는 잠재력이있는 것입니다 (최소한 20 %까지 예측합니다). , IE8- Visual Studio 등
slebetman 2014 년

1
또한 node.js-노드 검사기. 그러나 node.js 프로그래머는 일반 자바 스크립트 프로그래머만큼 기본 및 / 또는 내 코드 수정 질문을 많이하지 않습니다.
slebetman 2014-08-25

40

디버거가 항상 완벽한 솔루션은 아니며 항상 디버깅을위한 솔루션이되어서는 안된다는 점을 덧붙이고 싶습니다. 다음은 디버거가 작동하지 않을 수있는 몇 가지 경우입니다.

  • 실패한 프로그램의 부분은 정말 크며 (아마도 모듈화 불량일까요?) 코드를 단계별로 시작할 위치를 정확히 알 수 없습니다. 모든 단계를 진행하는 데 너무 많은 시간이 소요될 수 있습니다.
  • 프로그램은 많은 콜백 및 기타 비선형 흐름 제어 방법을 사용하므로 단계별로 디버거를 혼란스럽게 만듭니다.
  • 프로그램은 다중 스레드입니다. 또는 더 나쁜 것은 경쟁 조건으로 인해 문제가 발생한다는 것입니다.
  • 버그가있는 코드는 버그가 발생하기 전에 여러 번 실행됩니다. 이것은 특히 메인 루프에서 문제가 될 수 있으며, 물리 엔진에서는 문제가 수치적일 수있는 경우에 더욱 심각 할 수 있습니다. 이 경우 중단 점을 설정하는 경우에도 버그가 나타나지 않고 여러 번 누르게됩니다.
  • 프로그램은 실시간으로 실행되어야합니다. 이것은 네트워크에 연결되는 프로그램에 대한 큰 문제입니다. 네트워크 코드에 중단 점을 설정하면 다른 쪽 끝은 단계를 통과 할 때까지 기다리지 않고 단순히 시간이 초과됩니다. 시스템 시계에 의존하는 프로그램 (예 : 프레임 스킵이있는 게임)도 그다지 좋지 않습니다.
  • 프로그램은 파일에 쓰기 또는 이메일 보내기와 같은 일종의 파괴적인 작업을 수행하고이를 통해 실행해야하는 횟수를 제한하려고합니다.
  • 함수 X에 잘못된 값이 도착하여 버그가 발생했다고 말할 수 있지만 이러한 값의 출처를 알 수 없습니다. 프로그램을 반복해서 실행하고 중단 점을 더 멀리 뒤로 설정하는 것은 매우 번거로울 수 있습니다. 특히 프로그램 전체에서 함수 X가 여러 곳에서 호출되는 경우.

이러한 모든 경우에 프로그램을 갑자기 중지하면 최종 결과가 달라 지거나 버그가 발생한 한 줄을 수동으로 검색하는 것이 너무 번거 롭습니다. 이는 버그가 잘못된 동작이든 충돌이든 똑같이 발생할 수 있습니다. 예를 들어, 메모리 손상으로 인해 크래시가 발생하면 크래시가 발생했을 때 메모리 손상이 처음 발생한 위치에서 너무 멀리 떨어져 유용한 정보가 남아 있지 않습니다.

그렇다면 대안은 무엇입니까?

가장 간단한 것은 단순히 로깅과 어설 션입니다. 다양한 지점에서 프로그램에 로그를 추가하고 얻은 결과를 예상 한 것과 비교합니다. 예를 들어 버그가 있다고 생각하는 함수가 처음부터 호출되는지 확인하십시오. 메서드 시작 부분의 변수가 당신이 생각하는 것과 같은지 확인하십시오. 중단 점과 달리 특별한 일이 발생하지 않는 많은 로그 행이 있어도됩니다. 나중에 로그를 통해 간단히 검색 할 수 있습니다. 예상과 다른 로그 라인에 도달하면 동일한 영역에 더 추가하십시오. 버그가있는 지역의 모든 줄을 기록 할 수있을만큼 충분히 작아 질 때까지 더 멀리 더 좁 힙니다.

어설 션은 최종 사용자에게 효과가 표시되는 것이 아니라 발생하는 잘못된 값을 트랩하는 데 사용할 수 있습니다. 잘못된 값을 빨리 포착할수록 해당 값을 생성 한 라인에 더 가까워집니다.

리팩터링 및 단위 테스트. 프로그램이 너무 크면 한 번에 하나의 클래스 또는 하나의 함수를 테스트하는 것이 좋습니다. 입력을 제공하고 출력을보고 예상과 다른 것을 확인하십시오. 전체 프로그램에서 단일 기능으로 버그를 좁힐 수 있다는 것은 디버깅 시간에 큰 차이를 만들 수 있습니다.

메모리 누수 또는 메모리 스톰 핑의 경우 런타임에이를 분석하고 감지 할 수있는 적절한 도구를 사용하십시오. 실제 손상이 발생한 위치를 감지하는 것이 첫 번째 단계입니다. 그런 다음 로그를 사용하여 잘못된 값이 도입 된 위치로 돌아갈 수 있습니다.

디버깅은 거꾸로 진행되는 프로세스임을 기억하십시오. 최종 결과 (버그)가 있고 그 이전의 원인을 찾습니다. 그것은 뒤로 작업하는 것에 관한 것이고 불행히도 디버거는 앞으로 나아갈뿐입니다. 좋은 로깅과 사후 분석을 통해 훨씬 더 나은 결과를 얻을 수 있습니다.


10
이것은 다른 질문에 대한 좋은 대답이 될 것입니다. 질문에 대한 잘못된 대답입니다 . 아마도 당신은 그 질문을하고 그것에 대한 답장으로 이것을 게시해야 할 것입니다.
Raedwald 2015

10
실제 질문은 "프로그램에 문제가있는 새로운 프로그래머 지원", "내가 기대하는 출력을 생성하지 못함"및 "스택 추적을 조사했지만 여전히 문제의 원인을 모릅니다"로 설명됩니다. . 이 모든 것이이 답변에 의해 지원됩니다. 또한 디버거가 수행하는 작업 을 설명 할 때 수행하지 않는 작업 을 설명하는 것도 똑같이 중요합니다 .
SlugFiller 2015

5
좋은 대답입니다. 저는 항상 디버거를 주요 도구로 사용하여 버그를 찾았습니다. 하지만 지금은 거대한 인프라 구성 요소가 많은 스레드와 많은 네트워크 코드 (클라이언트 / 서버)를 사용하는 프로젝트에서 일하고 있으며 디버거가 나를 돕는 마지막 것임을 알 수 있습니다. 좋은 오래된 디버거에 의존하는 대신 다른 도구를 사용해야하는 많은 것들을 언급했습니다 (가장 중요 : 로깅).
Tim Schmelter 2017

"버그가 함수 X에 도착하는 잘못된 값으로 인해 발생했음을 알 수 있지만 이러한 값의 출처를 모릅니다." 이것은 특히 디버깅하기가 어렵습니다. 보통 그런 것을 고치는 방법은 무엇입니까?
Ayxan Haqverdili

3
@Ayxan 어느 정도까지는 어설 션에서 함수 중단을 관리했다면 호출 스택을 사용하여 호출자를 가져올 수 있습니다. 그러나 그것만으로는 가치의 출처를 알 수 없습니다. 왜냐하면 그 가치는 이전 라인에서 온 것일 가능성이 높기 때문입니다. 기본적으로 다양한 변수를 통해 값을 따라 가야합니다. 데이터가 이동하는 경로에 대해 잘 알고있는 경우 로그 인쇄를 여러 개 만들고 "잘못되는"위치를 좁힐 수 있습니다. 그렇지 않은 경우 기본적으로 모든 단계 뒤로 프로그램을 별도로 실행 (오류 재현)해야합니다.
SlugFiller
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.