2016-12-27 1 views
3

저는 C++을 사용할 프로그래밍 코스를 가르치고 있습니다. 내가 디버거를 사용하는 방법에 대한 유인물을 함께 넣고 학생들은 이름과 성이 해시 코드 생성기의 실행을 통해 단계가 싶었다 :범위 기반 for 루프에서 계속하면 중단 점을 다시 트리거하지 않습니까?

int nameHash(string first, string last){ 
    /* This hashing scheme needs two prime numbers, a large prime and a small 
    * prime. These numbers were chosen because their product is less than 
    * 2^31 - kLargePrime - 1. 
    */ 
    static const int kLargePrime = 16908799; 
    static const int kSmallPrime = 127; 

    int hashVal = 0; 

    /* Iterate across all the characters in the first name, then the last 
    * name, updating the hash at each step. 
    */ 
    for (char ch: first + last) { 
     /* Convert the input character to lower case, then make sure it's 
     * between 0 and the small prime, inclusive. 
     */ 
     ch = tolower(ch) % (kSmallPrime + 1); 
     hashVal = (kSmallPrime * hashVal + ch) % kLargePrime; 
    } 
    return hashVal; 
} 

이 GDB를 사용하여, 나는이 포함 된 줄에 중단 점을 설정 범위 기반 for 루프 :

(*) for (char ch: first + last) 

gdb로 프로그램을 실행했을 때 예상대로 여기에서 중단 점이 트리거되었습니다. 그러나 실행을 계속하면 중단 점이 다시 트리거되지 않고 프로그램이 완료 될 때까지 실행됩니다.

이 동작을 시스템에서 일관되게 재현 할 수 있습니다. 루프 본문에 브레이크 포인트를 설정하고 적중 될 때까지 실행하면 루프의 맨 위에 중단 점을 추가하고 "계속"을 누르면 디버거가 루프 중단 점을 건너 뜁니다.

범위 기반 for 루프가 일련의 다른 초기화 단계로 확장되어 (디버그 창에서 생성 된 임시 변수가 실제로 표시됨) 브레이크 포인트가 루프 단계가 아닌 초기화 단계. 그렇다면 이해할 만하지만 놀랍도록 반 직관적입니다.

이 문제에 대한 현재 해결 방법은 루프의 맨 위에 루프 안의 첫 번째 문에 중단 점을 설정하는 것이지만 직관적이지 못하며 교육적 관점에서 볼 때 앞으로의 잘못된 조언입니다.

  1. 내 분석이 정확 :

    내 질문은 다음과 같습니다?

  2. 내 gdb 버전과 관련이 있습니까? 내가 할 수있는 GDB를 얻기 위해 5.4.0 20160609.
  3. 이 방법을
    • 우분투 16.04 및
    • g ++ (5.4.0-6ubuntu1 ~ 16.04.4 우분투)가되어 사용하고 있습니다 범위 기반 for 루프의 중단 점을 초기화 단계가 아닌 루프 본문의 중단 점으로 처리합니까?
+1

"이 OS 또는 Qt Creator는 버전에 맞습니까?" 그것은 GDB의 변종 일 수 있습니다. Visual C++ 및/또는 Clang으로이 작업을 시도해보고 동일한 결과를 얻었는지 확인하십시오. 결국 Qt Creator의 디버거는 단지 그래픽 프론트 엔드에 불과합니다. – MrEricSir

+0

@MrEricSir 전화하세요! 이것은 GDB 문제입니다. 나는 몇몇 구글 검색으로 이것에 관해 무엇인가를 발견 할 수 없다. 그래서 나는 그것을 다시 집중하도록 질문을 업데이트했다. – templatetypedef

+0

프로덕션 디버깅을 위해 어셈블러 뷰로 전환 한 다음 코드의 반복 부분에 중단 점을 설정할 수 있습니다. 그러나 나는 "어셈블러 뷰로 전환"이 아마 가르쳐야 할 * * * 일이 아니라고 생각합니다! –

답변

2

아직 존재하지 않는 소스 코드와 실행의 일대일 매핑이 필요합니다. for 라인은 각 루프 반복에서 "반복"되지 않습니다. 루프가 작동하는 방법을 소개하고 설명합니다.

for 줄의 중단 점은 한 번만 동작하는 것으로 예상됩니다. C, C++, JavaScript, 다르게 작동하는 디버거를 사용하는 것을 기억하지 않습니다.

본문의 첫 줄에 중단 점을 넣으십시오. 그것은 반복되는 몸입니다.

+0

그런데 C++ 11을 교재로 사용하는 것이 좋지만, const 참조로 해당 문자열을 수락하는 것이 좋습니다.'첫 번째 + 마지막'연결은 불필요하게 비효율적 인 것처럼 보입니다. for (char ch : boost :: join (first, last))'를 생각해 보라. –

+0

while 루프의 동등한 중단 점 (breakpoint)이 각 반복에서 중단 점을 트리거하므로 혼란 스럽기 때문에 놀랐습니다. 또한 여기에 불필요한 복사가 있다는 것은 절대적으로 옳습니다. 그러나 이것이 C++에서의 첫 번째 엿볼이기 때문에 Boost를 보여주지 않을 것입니다. :-) – templatetypedef

+0

@templatetypedef : _ "while 루프의 동등한 중단 점 (breakpoint)이 각 반복마다 중단 점을 트리거하기 때문에 놀랐습니다."_ 나는 손끝이 필요하지 않지만 그것은 내 기대가 아니다. –

1

나는 gdb으로뿐만 아니라 MSVC2015QtCreator를 사용하여 조준을 재현하는 데 성공했습니다. 적어도 내 환경에서는 이것도 일반 for(int i=0; ...) 루프에 적용됩니다.

나는 웹을 조금 검색 한 및 gdb을 위해 그 내용의 online doc의 정보를 찾기 위해 관리 :

단계의 명령은 소스 라인의 첫 번째 명령에서 정지합니다. 이 여러 등

그렇지 않으면 루프, 스위치 문에서 발생할 수있는 정지, 이것은 관찰 된 행동을 설명 할 수 방지 할 수 있습니다. 그러나 그것을 비활성화하거나 덮어 쓸 수있는 방법이 있는지 찾을 수 없었습니다.나는 몇 가지 추가 검사를 완료했습니다

편집 할 수 있습니다. 루프에서 마지막 명령을 한 후 단계를 수행하면 실제로 for 문으로 돌아갑니다. 중단 점 만 건너 뜁니다. 이 의 지정된 위치에서 코드를 실행하기 직전에

중단 점은 프로그램을 중지합니다 : breakpoints 섹션의 문서에서

것을 주장한다.

이는 단지 야생 실행이지만 루프 실행 중에는 위치 just before에 도달 할 수 없습니다. 루프 내에서는 조건 평가로 돌아갑니다. 일부 초기화가 발생하여 중단 점에서 중지 할 수없는 루프 진입 점을 이미 통과했습니다.

+0

보통'for' 루프에서 초기화, 조건부 종료 및 증분에 해당하는 동일한 행의 세 위치에 중단 점을 설정할 수 있습니다 (최소한 하나 이상의 명령문이있을 때 Visual Studio에서 가장 많이 사용하는 디버거와 함께). 한 줄에 중단 점을 만들 때 커서가있는 열은 중단 할 문을 결정하는 데 사용됩니다. –

+0

이것은 일반적으로 사실 일 수 있습니다. 그러나'gdb'에 대해서 QtCreator와 함께 사용하고 있습니다. 예를 들어'for (int i = 0; i Dusteh

+0

줄의 어느 부분에 중단 점을 만들지는 중요하지 않습니까? 'int i = 0'의 중단 점은 한 번 멈추어야하지만,'i

관련 문제