다음을 통해 공유


디버깅 API 기능

업데이트: 2007년 11월

이 항목에서는 CLR(공용 언어 런타임) 디버깅 서비스에서 제공하는 기능에 대해 간략하게 설명합니다. 이 항목에는 다음 하위 단원이 포함되어 있습니다.

프로그램에 연결 또는 프로그램 실행

실행 제어

프로그램 상태 검사

프로그램 상태 수정

편집하며 계속하기 사용

함수 실행

동적으로 코드 삽입

프로그램에 연결 또는 프로그램 실행

CLR을 사용하면 실행 중인 프로그램에 디버거를 연결하거나 프로세스를 시작할 수 있습니다. CLR 디버깅 서비스에서는 처리되지 않은 예외를 throw하는 프로그램에 디버거를 연결할 수 있도록 하여 JIT(Just-In-Time) 디버깅을 지원합니다. 그러나 디버깅 가능한 모드로 실행되고 있지 않은 프로그램에서는 사용할 수 있는 디버깅 정보가 적을 수 있습니다. 이러한 문제를 방지하기 위해 프로그램은 항상 디버깅 가능한 모드로 실행될 수 있습니다. 디버깅 가능한 모드에 대한 자세한 내용은 다음을 참조하십시오.

실행 제어

CLR 디버깅 서비스에서는 프로그램 실행을 제어하기 위한 몇 가지 방법을 제공합니다. 이러한 방법에는 중단점, 한 단계씩 실행, 예외 알림, 함수 실행 및 프로그램 시작과 종료와 관련된 다른 이벤트가 있습니다.

CLR 디버깅 API에서는 관리 코드에 대해서만 실행 제어를 제공합니다. 실행 제어를 비관리 코드에서 수행하려면 디버거에서 별도로 이 기능을 구현해야 합니다.

중단점

중단이 발생할 위치의 코드 및 MSIL(Microsoft Intermediate Language) 또는 네이티브 오프셋을 지정하여 중단점을 만들 수 있습니다. 중단점에 도달하면 디버거가 알림을 받습니다. 디버깅 API에서는 조건부 중단점을 직접 지원하지 않지만 디버거에서는 중단점에 대응하여 식을 계산하고 사용자에게 중지 사실을 알릴지 여부를 결정하여 이러한 중단점을 구현할 수 있습니다.

단계별 실행

CLR 디버깅 서비스에서는 다양한 단계별 실행 기능을 제공합니다. 프로그램에서는 한 번에 하나의 명령을 실행(한 단계씩 실행)하거나 한 번에 하나의 명령 범위를 실행(범위별 실행)할 수 있습니다. 함수를 건너뛰거나, 한 단계씩 실행하거나, 함수에서 나갈 수 있습니다. CLR 디버깅 서비스는 단계별 실행 작업을 중단하는 예외가 발생할 경우 디버거에 알릴 수도 있습니다.

디버깅 서비스에서는 비관리 코드를 단계별로 실행하는 기능을 직접 지원하지는 않지만 단계별 실행 작업이 비관리 코드에 도달하면 콜백을 제공하여 디버거에 제어를 전달합니다. 또한 비관리 코드에서 관리 코드에 진입하려고 하는 시점을 디버거가 파악할 수 있도록 하는 기능을 제공합니다.

CLR에서는 소스 수준 단계별 실행을 직접 제공하지 않습니다. 디버거는 자체 소스 매핑 정보와 함께 범위별 실행을 사용하여 이 기능을 제공할 수 있습니다. 기호 저장소 인터페이스를 사용하여 소스 수준 정보를 가져올 수 있습니다. 이러한 인터페이스에 대한 자세한 내용은 진단 기호 저장소(관리되지 않는 API 참조)를 참조하십시오.

예외

CLR 디버깅 서비스를 사용하면 관리 코드의 첫째 예외와 둘째 예외에 대해 디버거에 알릴 수 있습니다. 각 지점에서 throw된 개체를 검사할 수 있습니다.

네이티브 예외가 관리 코드까지 전파되지 않으면 CLR에서 이러한 예외를 처리하지 않습니다. 그러나 CLR 디버깅 서비스와 공유되는 Win32 디버깅 서비스를 사용하여 관리되지 않는 예외를 처리할 수 있습니다.

프로그램 이벤트

여러 프로그램 이벤트가 발생하면 CLR 디버깅 서비스에서 디버거에 알립니다. 이러한 이벤트에는 프로세스 만들기 및 종료, 스레드 만들기 및 종료, 응용 프로그램 도메인 만들기 및 종료, 어셈블리 로딩 및 언로딩, 모듈 로딩 및 언로딩, 클래스 로딩 및 언로딩 등이 있습니다. 성능 향상을 위해 모듈에 클래스 로딩 및 언로딩 이벤트를 사용하지 않도록 설정할 수 있습니다. 기본적으로 클래스 로딩 및 언로딩 이벤트는 사용되지 않습니다.

스레드 제어

CLR 디버깅 서비스에서는 관리되는 개별 스레드를 일시 중단하거나 다시 시작하는 인터페이스를 제공합니다.

프로그램 상태 검사

CLR 디버깅 서비스에서는 프로세스가 중지된 상태일 때 관리 코드를 실행하는 프로세스 부분을 검사하는 자세한 방법을 제공합니다. 프로세스를 검사하여 실제 스레드의 목록을 가져올 수 있습니다.

스레드를 검사하여 호출 스택을 검사할 수 있습니다. 스레드의 호출 스택은 체인 수준 및 스택 프레임 수준에서 분해됩니다. 호출 스택은 먼저 체인으로 분해됩니다. 체인은 완전하게 관리되거나 관리되지 않는 스택 프레임을 포함하는 연속된 논리 호출 스택 세그먼트입니다. 또한 단일 체인에 있는 관리되는 호출 프레임은 모두 같은 CLR 컨텍스트를 공유합니다. 체인은 관리되거나 관리되지 않을 수 있습니다.

또한 각각의 관리되는 체인은 단일 스택 프레임으로 다시 분해될 수 있습니다. 각 스택 프레임은 하나의 메서드 호출을 나타냅니다. 스택 프레임을 쿼리하여 실행 중인 코드를 가져오거나 해당 인수, 지역 변수 및 네이티브 레지스터를 가져올 수 있습니다.

관리되지 않는 체인에는 스택 프레임이 포함되지 않습니다. 대신 관리되지 않는 체인은 비관리 코드에 할당된 스택 주소 범위를 제공합니다. 비관리 코드 디버거는 스택의 관리되지 않는 부분을 디코딩하고 스택 추적을 제공합니다.

참고

CLR 디버깅 서비스에서는 소스 코드에 있는 지역 변수 개념을 지원하지 않습니다. 디버거는 할당에 지역 변수를 매핑합니다.

또한 CLR 디버깅 서비스에서는 전역, 클래스 정적 및 스레드 지역 변수에 대한 액세스를 제공합니다.

프로그램 상태 수정

CLR 디버깅 서비스를 사용하면 실행하는 동안 디버거가 명령 포인터의 실제 위치를 변경할 수 있지만 이는 위험한 작업입니다. 다음 조건에 해당되면 명령 포인터를 성공적으로 변경할 수 있습니다.

  • 현재 명령 포인터 및 대상 명령 포인터가 둘 다 시퀀스 위치에 있습니다. 시퀀스 위치는 대략 문의 경계를 나타냅니다.

  • 대상 명령 포인터가 예외 필터, catch 블록 또는 finally 블록에 없습니다.

  • catch 블록 내에 있을 경우 대상 명령 포인터가 catch 블록 외부에 없습니다.

  • 대상 명령 포인터가 현재 명령 포인터와 같은 프레임에 있습니다.

명령 포인터의 실제 위치가 변경되면 현재 명령 포인터 위치에 있는 변수가 대상 명령 포인터 위치에 있는 변수에 매핑됩니다. 대상 명령 포인터 위치의 가비지 수집 참조가 올바로 초기화됩니다.

명령 포인터가 변경되면 CLR 디버깅 서비스는 캐시된 스택 정보를 유효하지 않은 것으로 표시하고 이후 필요할 때마다 정보를 새로 고칩니다. 프레임 및 체인과 같은 스택 정보에 대한 포인터를 캐시하는 디버거에서는 명령 포인터를 변경한 후 이 정보를 새로 고쳐야 합니다.

또한 프로그램이 중지되면 디버거에서 프로그램의 데이터를 수정할 수 있습니다. 디버거에서는 함수가 실행 중일 때 함수의 지역 변수 및 인수를 검사와 비슷한 방식으로 변경할 수 있습니다. 디버거에서는 배열 및 개체의 필드와 정적 필드 및 전역 변수를 업데이트할 수도 있습니다.

편집하며 계속하기 사용

편집하며 계속하기 기능을 사용하면 디버깅 세션 중에 소스 코드를 편집하고, 수정된 소스를 다시 컴파일하며, 실행 파일을 처음부터 다시 실행하지 않고 디버깅 세션을 계속할 수 있습니다. 기능 면에서 편집하며 계속하기는 디버깅 중인 나머지 실행 파일의 런타임 상태를 유지하면서 디버거에서 실행 중인 코드를 수정할 수 있는 기능을 제공합니다.

함수 실행

디버거에서 사용자 식 및 개체의 동적 속성을 실행하려면 디버깅되는 프로세스의 코드를 실행하는 방법이 필요합니다. CLR 디버깅 서비스를 사용하면 디버거에서 함수 또는 메서드 호출을 만들어 디버기 프로세스 내에서 실행할 수 있습니다.

예를 들어 기존 코드에 교착 상태가 트리거되는 등 위험해질 수 있으므로 CLR은 디버거에서 이러한 작업을 중단할 수 있도록 합니다. 실행이 성공적으로 중단되면 스레드는 실행이 발생하지 않았던 것처럼 처리되는데 예외적으로 부분 실행의 결과로 인해 지역 변수가 의도하지 않은 영향을 받았을 수 있습니다. 함수가 관리되지 않는 코드나 블록으로 호출되면 실행을 끝내지 못할 수도 있습니다.

함수 실행이 완료되면 CLR은 콜백을 사용하여 실행이 정상적으로 완료되거나 함수가 예외를 throw했는지 여부를 디버거에 알립니다. ICorDebugValueICorDebugValue2 메서드를 사용하여 실행 결과를 검사할 수 있습니다.

함수 실행이 발생할 스레드는 관리 코드 내 가비지 수집이 발생하지 않을 안전한 지점에서 중지되어야 합니다. 처리되지 않은 예외에 함수 실행을 사용할 수도 있습니다. 최적화되지 않은 코드에서는 이렇게 안전한 지점이 매우 많으며 대부분의 중단점이나 MSIL 수준 단계별 실행 작업이 1에서 완료됩니다. 그러나 최적화된 코드에서는 이러한 지점을 찾기가 어렵습니다. 전체 함수에 안전한 지점이 없을 수도 있습니다. 가비지 수집에 대해 안전한 지점의 빈도는 함수마다 다릅니다. 최적화되지 않은 코드에서도 1에서 중지하지 않을 수 있습니다. 최적화된 코드에서든 최적화되지 않은 코드에서든 ICorDebugController::Stop 메서드가 안전한 지점에 도달하는 경우는 매우 드뭅니다.

CLR 디버깅 서비스에서는 스레드의 새 체인을 설정하여 함수 실행을 시작하고 요청된 함수를 호출합니다. 실행이 시작되면 실행 제어, 검사, 함수 실행 등과 같은 디버깅 API의 모든 측면을 사용할 수 있습니다. 중첩된 실행이 지원되며 중단점이 정상적으로 처리됩니다.

동적으로 코드 삽입

일부 디버거에서는 사용자가 직접 실행 창에 임의의 문을 입력하고 해당 문을 실행할 수 있습니다. CLR 디버깅 서비스에서는 이 시나리오를 지원합니다. 동적으로 삽입할 수 있는 코드에는 비지역 goto 문을 사용할 수 없다는 등의 제한이 없습니다.

동적 코드 삽입은 편집하며 계속하기와 함수 실행을 함께 사용하여 구현됩니다. 삽입할 코드는 함수에서 래핑되고 편집하며 계속하기를 사용하여 삽입됩니다. 그런 다음 삽입된 함수가 실행됩니다. 필요한 경우 즉시 영구적인 파생 효과가 발생하도록 ByRef로 선언되는 인수를 사용하는 래퍼 함수를 제공할 수 있습니다.

참고 항목

기타 리소스

.NET Framework에서 디버깅

CLR 디버깅 개요

디버깅(관리되지 않는 API 참조)