콘솔 / stdout으로 인쇄하는 것이 좋은 디버깅 전략입니까?


11

다음과 같은 기능이 있다고 가정 해 봅시다.

public void myStart()
{
    for (int i = 0; i<10; i++) myFunction(i); 
}


private int myFunction(int a)
{

    a = foo(a);
    a = bar(a);
    return a; 
}

private int foo(int a)
{
    //do something here

    //something gnarly here

    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

이제 어떤 이유로 든 코드가 작동하지 않습니다. 아마도 오류가 발생했을 수 있습니다. 아마도 잘못된 값을 반환하거나 무한 루프에 빠졌을 수 있습니다.

첫해 프로그래머가 가장 먼저 콘솔로 출력합니다 (디버거 사용법을 배우기 전에 Hello World를 인쇄하는 방법을 배웠습니다).

예를 들어이 코드를 디버깅하기 위해 다음을 수행 할 수 있습니다.

private int myFunction(int a)
{
    print("before foo: a=" + a); 
    a = foo(a);
    print("before bar: a=" + a);
    a = bar(a);

    return a; 
}

private int foo(int a)
{
    //do something here
    print ("foo step1: a=" + a); 

    //something gnarly here
    print ("foo step2: a=" + a + " someOtherValue="+ someOtherValue + " array.length= " + someArray.length()); 
    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

이제 코드를 실행하고 콘솔 출력이 커져 문제가 발생한 위치를 추적 할 수 있습니다.

물론 대안은 중단 점을 설정하고 각 지점에서 코드를 단계별로 진행하는 것입니다.

콘솔로 인쇄 할 때의 주요 이점 중 하나는 개발자가 단계 등을 클릭하지 않고도 한 번에 값의 흐름을 볼 수 있다는 것입니다.

그러나 단점은 코드가 이러한 모든 인쇄 문으로 가득 차서 제거해야한다는 것입니다.

(디버거가 특정 값만 로그에 인쇄하도록 지시 할 수 있습니까? 그러면 실제로 코드를 수정하지 않고도 중단 점을 쉽게 추가하거나 제거 할 수 있습니다.)

나는 여전히 콘솔 인쇄를 기본 디버깅 방법으로 사용하고 있는데, 이것이 다른 곳과 비교하여 이것이 얼마나 일반적이고 효과적인지 궁금합니다.


1
디버거를 사용하는 방법을 배우고 적절한 로깅 프레임 워크를 사용해야합니다. 항상 존재하지는 않지만 콘솔로 인쇄하는 것보다 훨씬 행복합니다.

7
디버거 사용 방법을 배우는 것이 중요하지만 printf 디버깅이 사용 가능한 유일한 디버깅 방법 인 경우가 많습니다 .
whatsisname

답변:


26

인쇄 문과 디버거는 상호 배타적이지 않습니다. 버그를 찾거나 식별하기 위해 사용할 수있는 다른 도구 일뿐입니다. 디버거를 건드리지 않는 방법을 주장하는 사람들이 있으며, 작성한 코드의 어느 곳에도 단일 로깅 / 인쇄 문이없는 사람들이 있습니다. 내 조언은 당신이 그 그룹 중 하나에 있고 싶지 않다는 것입니다.

대신 로깅 사용법을 배우고 디버거 사용법을 배우십시오. 경험을 바탕으로 (거의 그것에 대해 생각할 필요없이) 올바른 도구를 선택하고 작업을 정확하고 효율적으로 수행 할 수 있습니다. 경험이 없으면 때로는 다른 것을 선택하고 변수를 탐색하거나 로그 파일을 탐색하는 데 시간이 조금 더 걸릴 수 있지만 이는 학습 과정의 일부입니다.

따라서 특정 질문에 대답하십시오. 예. 인쇄를 사용하여 실행을 추적하는 것이 좋고 널리 사용되는 디버깅 전략입니다. 하나...

print 문을 사용하는 대신 로깅 프레임 워크를 사용하십시오. 로깅 프레임 워크에는 로깅 레벨 개념이 있으므로 전체 로그 메시지를 추가 할 수 있지만 각 레벨에 대한 레벨을 선택할 수 있습니다. 응용 프로그램이 정상적인 조건에서 실행되는 경우 중요한 항목 만보고되도록 수준이 오류 또는 경고가됩니다. 그러나 코드를 추적하고 실행 흐름을 이해해야하는 경우 로거를 INFO 또는 DEBUG로 변경하면 코드에 이미있는 모든 "인쇄"문이 추가 정보를보고합니다.

로깅 프레임 워크 사용 ...

  1. 완료 한 후 모든 인쇄물을 삭제할 필요는 없습니다.
  2. 코드에 남겨둔 지문은 나중에 귀하 또는 다른 개발자가 동일한 코드를 디버깅하는 데 도움이 될 수 있습니다
  3. 삭제 한 인쇄물을 추가 할 때마다 코드를 다시 작성하지 않고도 필드에서이 코드를 디버깅 할 수 있습니다.
  4. 콘솔 만이 아니라 원하는 곳에서 로깅 메시지를 리디렉션 할 수 있습니다. 그들은 파일, syslog, DB, 소켓 등으로 갈 수 있습니다.

업데이트 : 방금 요청한 끝에 "디버거에 특정 값만 로그에 인쇄하도록 지시 할 수 있습니까?" 사용하는 디버거에 따라 다릅니다. 많은 최신 디버거를 사용하면 중단 점에 도달했을 때 호출 할 동작을 정의 할 수 있습니다. 일부 (VS 및 WinDbg에서이 작업을 수행함)에서 "이를 인쇄하고 다시 시작"을 지정할 수 있습니다. Visual Studio에서는 "중단 점"대신 "추적 점"이라고합니다.


첫 번째 단락에 +1 디버거와 로그는 매우 다른 두 가지 문제를 해결합니다.
Blrfl

1
그러나 코드에 로그 문을 남겨두면 추악하다는 데 동의하지 않습니까?
dwjohnston

1
어떤 종류의 로그 문을 남길지에 따라 다릅니다. 방금 "logger.error ("WHAT ")"를 찾아서 제거했습니다. 그렇지 않으면 로깅 코드를 나머지 코드처럼 취급합니다. 형식을 지정하고 멋지게 보이게하고 유익하게 만드십시오. 네, 인쇄 문을 뿌릴 때마다 줄이 너무 많아서 그것에 의지해야 할 때가있었습니다. 그러나 일반적으로 전체 파일에 10-20 개의 로그 문 (합리적인 크기와 크기가 아닌 파일 / 클래스)을 갖는 것은 전혀 나쁘지 않습니다.
DXM

예를 들어 생산 시스템이있는 경우 다양한 중요 변수를 사용하면서 로깅 할 수 있으므로 일부 로그 문을 남겨두면 유용 할 수 있습니다. 오류 발생 하면 생산에서 발생한 일을 즉시 볼 수 있습니다 환경. 그러나 개발 상황에서는 지저분 해 보입니다. 예를 들어, 파싱 함수를 작성 중이고 정규 표현식을 제대로 얻지 못했기 때문에 진행 상황을 확인하고 결국 정렬하기 위해 일련의 로그 문을 넣습니다. 나는 그것이 가치를 더해 줄 것이라고 생각하지 않는다.
dwjohnston

1
@ Izkata : 그것은 모두 특정 버그의 세부 사항과 코드가 이미 로깅 한 양에 달려 있습니다. 내가 겪고 싶은 요점은 항상 로깅 문을 가지고 있고 다른 수준에서 그것들을 갖는 것의 가치가 있다는 것입니다. ERR-> WARN ...-> DEBUG. 매우 구체적인 내용이 필요한 경우 반드시 인쇄 문 추가를 시작하십시오. 그러나 "print"를 로깅 문으로 사용하는 사람에 대한 나의 대답은 항상 프레임 워크로 전환하여 사용하기 시작합니다.
DXM

3

로깅 / 프린팅 및 디버거는 서로 다른 강도와 약점이있는 보완 기술입니다. 둘 다 사용하는 것이 가장 좋습니다. 그러나 전반적으로 디버거는 대부분의 경우 우수한 도구이며 로깅 / 인쇄는 실제로 더 나은 것에 대해서만 사용되어야한다고 생각합니다.

디버거의 장점 :

  • 미리 인쇄하려고 생각한 값뿐만 아니라 전체 프로그램 상태를 검사 할 수 있습니다. 피드백주기를 1 초 미만으로 줄여 디버깅 프로세스 속도 를 크게 높일 수 있습니다 . 버그에 도달하는 데 시간이 걸리는 경우 특히 중요합니다.
  • 호출이 어디에서 왔는지 확인할 수 있으며 스택 추적에서 값을 검사 할 수도 있습니다.
  • 컴파일 된 이진 또는 바이트 코드 만 있기 때문에 쉽게 수정할 수없는 디버그 언어 (언어 / 플랫폼에 따라 다름)를 디버깅 할 수 있습니다.

로깅 / 인쇄의 장점 :

  • 특별한 디버그 빌드 또는 구성이 필요하지 않습니다. 항상 작동합니다.
  • 재현하기 어렵고 거의 발생하지 않는 오류를 분석하는 데 사용할 수 있습니다.
  • 디버거로 인한 일시 중지가 버그를 쉽게 사라지게 할 수있는 타이밍 종속 오류를 분석하는 데 사용할 수 있습니다.
  • 여가 시간에 분석 할 수있는 영구적 인 정보를 제공합니다. 프로그램 흐름의 다른 지점에서 출력간에 앞뒤로 이동할 수 있습니다.

로깅의 또 다른 장점은 코드를 통과하는 열 번째 단계에서 문제가 발생했을 때 실제로 어떻게 도착했는지에 대한 역 추적을 사용할 수 있다는 것입니다. 대부분의 디버거에는 리버스 버튼이 없지만 고급 함수가 호출 된 값을 기록하면 최소한 재현 가능한 경우에 가깝습니다.
Christopher Creutzig

1

예를 들어 표준 출력으로 인쇄하는 것은 코드를 디버깅하는 좋은 전략이 될 수 있습니다.

  • 나는 특히 오류를 완전히 이해하지 못하는 경우 코드의 다른 수준에서 무슨 일이 일어나고 있는지 확인하기 위해 많은 인쇄 진술을 사용합니다.

  • 또는 오류에 코드의 어떤 부분이 문제의 원인인지 정확하게 알려주는 자세한 정보가 없을 수 있습니다.

그러나 도구 디버깅에 익숙해 져야하지만 사용하는 언어 나 플랫폼에 따라 많은 것이 있습니다.

또한 다른 방법은 로깅입니다 .Android 응용 프로그램에서 작업 할 때 항상 오류를 기록하고 예외 처리를 사용하면 예외 발생의 스택 추적 또는 오류 메시지를 쉽게 기록 할 수 있습니다.


3
이 게시물은 읽기 어렵습니다 (텍스트의 벽). 더 나은 형태로 편집 하시겠습니까 ?
gnat

조금 읽을 수있게 만들었습니다. 이전에 죄송합니다!
Plaix
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.