예외가 발생할 때까지 GDB에서 응용 프로그램 실행


102

다중 스레드 응용 프로그램에서 작업 중이며 GDB를 사용하여 디버깅하고 싶습니다.

문제는 내 스레드 중 하나가 메시지와 함께 계속 죽어 간다는 것입니다.

pure virtual method called
terminate called without an active exception
Abort

나는 그 메시지의 원인을 알고 있지만 내 스레드에서 그것이 발생하는 곳을 모릅니다. 역 추적이 정말 도움이 될 것입니다.

GDB에서 내 앱을 실행하면 스레드가 일시 중지되거나 다시 시작될 때마다 일시 중지됩니다. 스레드 중 하나가 해당 예외와 함께 죽을 때까지 내 앱이 계속 정상적으로 실행되기를 원합니다.이 시점에서 모든 것이 중지되어 역 추적을 얻을 수 있습니다.


GDB가 일시 중지 할 때보고하는 신호는 무엇입니까? 다음과 같은 명령을 실행할 수 있어야합니다handle SIGUSR1 pass noprint nostop
Hasturkun

답변:


147

"catchpoint"( catch throw)를 사용하여 예외가 생성 된 지점에서 디버거를 중지 할 수 있습니다 .

gdb 설명서에서 발췌 한 다음 은 catchpoint 기능을 설명합니다.


5.1.3 캐치 포인트 설정

catchpoint를 사용하여 C ++ 예외 또는 공유 라이브러리로드와 같은 특정 종류의 프로그램 이벤트에 대해 디버거가 중지되도록 할 수 있습니다. catch 명령을 사용하여 catchpoint를 설정합니다.

  • 이벤트 잡기

    이벤트 가 발생 하면 중지 합니다. 이벤트는 다음 중 하나 일 수 있습니다.

    • 던지다

      C ++ 예외 발생.

    • 잡기

      C ++ 예외 포착.

    • 임원

      exec에 대한 호출. 현재 HP-UX에서만 사용할 수 있습니다.

    • 포크

      포크 호출. 현재 HP-UX에서만 사용할 수 있습니다.

    • vfork

      vfork 호출. 현재 HP-UX에서만 사용할 수 있습니다.

    • libname 로드 또는 로드

      공유 라이브러리의 동적로드 또는 라이브러리 libname의로드. 현재 HP-UX에서만 사용할 수 있습니다.

    • libname 언로드 또는 언로드

      동적으로로드 된 공유 라이브러리의 언로드 또는 라이브러리 libname의 언로드. 현재 HP-UX에서만 사용할 수 있습니다.

  • tcatch 이벤트

    한 정거장 만 사용할 수있는 캐치 포인트를 설정합니다. 캐치 포인트는 이벤트가 처음 잡히면 자동으로 삭제됩니다.

info break명령을 사용하여 현재 캐치 포인트를 나열하십시오.

현재 GDB에서 C ++ 예외 처리 (catch throw 및 catch catch)에 대한 몇 가지 제한 사항이 있습니다.

  • 대화식으로 함수를 호출하면 GDB는 일반적으로 함수 실행이 완료 될 때 제어를 반환합니다. 그러나 호출에서 예외가 발생하면 호출은 제어를 반환하는 메커니즘을 우회하여 프로그램을 중단하거나 중단 점에 도달하거나 GDB가 수신하는 신호를 포착하거나 종료 할 때까지 계속 실행되도록 할 수 있습니다. 예외에 대한 catchpoint를 설정 한 경우에도 마찬가지입니다. 예외에 대한 catchpoint는 대화식 호출 내에서 비활성화됩니다.

  • 대화식으로 예외를 발생시킬 수 없습니다.

  • 예외 처리기를 대화식으로 설치할 수 없습니다.

때때로 catch는 예외 처리를 디버그하는 가장 좋은 방법이 아닙니다. 예외가 발생한 위치를 정확히 알아야하는 경우, 해제가 발생하기 전에 스택을 볼 수 있으므로 예외 처리기가 호출되기 전에 중지하는 것이 좋습니다. 대신 예외 처리기에 중단 점을 설정하면 예외가 발생한 위치를 찾기가 쉽지 않을 수 있습니다.

예외 처리기가 호출되기 직전에 중지하려면 구현에 대한 지식이 필요합니다. GNU C ++의 경우 다음 ANSI C 인터페이스가있는 __raise_exception이라는 라이브러리 함수를 호출하여 예외가 발생합니다.

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

스택 해제가 발생하기 전에 디버거가 모든 예외를 포착하도록하려면 __raise_exception에 중단 점을 설정합니다 (중단 점, 감시 점 및 예외 섹션 참조).

id 값에 의존하는 조건부 중단 점 (단절 조건 섹션 참조)을 사용하면 특정 예외가 발생할 때 프로그램을 중지 할 수 있습니다. 여러 조건부 중단 점을 사용하여 여러 예외가 발생할 때 프로그램을 중지 할 수 있습니다.


잡을 예외 유형을 지정할 수도 있습니다 (예 : catch throw std::runtime_exception.
SCAI

5

__pure_virtual에 중단 점 설정


@JeffreyHill 답변에서 이제 __cxa_pure_virtual이라고합니다. 직접 확인하는 방법을 모르기 때문에 답을 수정하고 싶지 않습니다. 나는 반대표를 던질 생각은 없지만, 지금은 답이 틀릴 수 있으므로 올바른 것을 아는 사람이 수정해야합니다.
Philipp Claßen

5

FWIW, 분명히 gcc 4.1에서 적절한 함수 이름이 변경되었으며이 함수에서 중단 점을 설정해야합니다.

__cxa_pure_virtual


0

아래 하나만 gdb 8.3에서 나를 위해 일했습니다.

break _Unwind_RaiseException

"catch throw"또는 "break __cxx_throw"가 작동하지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.