다음을 통해 공유


CLR 디버깅 개요

CLR(공용 언어 런타임) 디버깅 API를 사용하면 도구 공급업체가 CLR 환경에서 실행되는 응용 프로그램을 디버깅하기 위한 디버거를 작성할 수 있습니다. CLR에서 지원되는 모든 종류의 코드를 디버깅할 수 있습니다.

CLR 디버깅 API는 기본적으로 비관리 코드로 구현됩니다. 따라서 디버깅 API는 COM(Component Object Model) 인터페이스 집합으로 표시됩니다. 디버깅 API는 다음 부분으로 구성됩니다.

  • CLR에서 구현되는 COM 개체 및 인터페이스의 컬렉션

  • 디버거에서 구현되어야 하는 COM 콜백 인터페이스의 컬렉션

이 개요는 다음과 같은 단원으로 구성됩니다.

  • CLR 디버깅 시나리오

  • API 범주

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

  • 실행 제어

  • 프로그램 상태 검사

  • 프로그램 상태 수정

  • 편집하며 계속하기 사용

  • 함수 실행

  • 동적으로 코드 삽입

  • 지원 환경

  • 관련 항목

CLR 디버깅 시나리오

다음 단원에서는 공용 언어 런타임 디버깅 API에서 일반적인 디버깅 시나리오를 처리하는 방법에 대해 설명합니다. 런타임에서는 일부 시나리오를 직접적으로 지원하며 다른 메서드를 지원하기 위해 현재 메서드와 상호 작용합니다.

Out-of-Process 디버깅

Out-of-process 디버깅에서는 디버거가 디버깅하고 있는 프로세스와 별도의 프로세스에 있습니다. 즉, 디버거가 디버기 외부에 있습니다. 이 시나리오에서는 디버거와 디버기 간의 상호 작용이 줄어듭니다. 따라서 프로세스를 더욱 정확하게 파악할 수 있습니다.

CLR 디버깅 API에서는 out-of-process 디버깅을 직접적으로 지원합니다. API에서는 디버거와 디버기의 관리되는 부분 간의 모든 통신을 처리하여 관리 코드 디버깅을 지원합니다.

CLR 디버깅 API도 out-of-process로 사용될 수 있지만 스레드 동기화와 같은 일부 디버깅 논리는 디버기에서 in-process로 발생합니다. 대부분의 경우 이 사항은 디버거에 투명하게 알려야 하는 구현 정보입니다. 스레드 동기화에 대한 자세한 내용은 CLR 디버깅 아키텍처를 참조하십시오. 그러나 디버깅 API를 out-of-process로 사용할 경우 크래시 덤프를 검사할 수 없다는 단점이 있습니다.

In-Process 디버깅

.NET Framework 버전 1.0 및 1.1의 CLR 디버깅 API에서는 프로파일러에서 디버깅 API의 검사 기능을 사용할 수 있는 제한된 in-process 디버깅을 지원했습니다. .NET Framework 2.0에서는 in-process 디버깅이 프로파일링 API와 더욱 일관성이 있는 기능 집합으로 바뀌었습니다. 이러한 변경 내용에 대한 자세한 내용은 프로파일링 개요에서 스택 스냅숏개체 검사 기능을 참조하십시오.

원격 프로세스 디버깅

원격 프로세스 디버깅에서는 디버거 사용자 인터페이스가 디버깅되고 있는 프로세스와 별도의 컴퓨터에 있습니다. 이 시나리오는 디버거와 디버기를 동일한 컴퓨터에서 실행할 때 디버거가 디버기를 방해하는 경우에 유용합니다. 이 문제의 원인은 다음과 같습니다.

  • 제한된 리소스

  • 위치 종속성

  • 운영 체제에 방해가 되는 버그

CLR 디버깅 API에서는 원격 프로세스 디버깅을 직접적으로 지원하지 않습니다. CLR 디버깅 API를 기반으로 하는 디버거는 디버기에서 out-of-process로 유지되어야 합니다. 따라서 이 솔루션을 사용하려면 디버기와 동일한 컴퓨터에 프록시 프로세스가 있어야 합니다.

비관리 코드 디버깅

관리 코드와 비관리 코드는 대개 같은 프로세스에 함께 있으므로 두 코드 형식을 동시에 디버깅할 수 있어야 합니다.

CLR 디버깅 API는 관리 코드와 비관리 코드 간의 경계를 단계별로 실행할 수 있는 기능을 제공하지만 비관리 코드 디버깅을 직접적으로 지원하지는 않습니다. 그러나 Win32 디버깅 기능을 공유하면 CLR 디버깅 API를 비관리 코드 디버거와 함께 사용할 수 있습니다.

또한 CLR 디버깅 API에서는 프로세스를 디버깅하기 위한 다음 두 가지 옵션을 제공합니다.

  • 부분 연결(Soft attach) 옵션 - 프로세스의 관리되는 부분만 디버깅합니다. 프로세스에 부분 연결된 디버거는 나중에 프로세스에서 분리할 수 있습니다.

  • 전체 연결(Hard attach) 옵션 - 프로세스의 관리되는 부분과 관리되지 않는 부분을 모두 디버깅하며 모든 Win32 디버그 이벤트가 디버깅 API를 통해 노출됩니다.

혼합 언어 환경

구성 요소 소프트웨어에서 각 구성 요소는 서로 다른 언어를 사용하여 작성될 수 있습니다. 디버거에서 데이터를 올바른 형식으로 표시하고 올바른 구문을 사용하여 식을 계산하는 등의 작업을 수행할 수 있도록 디버거가 다른 언어를 인식해야 합니다.

CLR에는 소스 언어라는 개념이 없기 때문에 CLR 디버깅 API에서는 혼합 언어 환경을 직접적으로 지원하지 않습니다. 디버거의 기존 소스 매핑 기능을 사용하여 지정한 함수를 함수가 구현된 언어에 매핑할 수 있어야 합니다.

다중 프로세스 및 분산 프로그램

구성 요소 프로그램에는 다른 프로세스에서 또는 전체 네트워크에 있는 다른 컴퓨터에서 실행되고 있는 구성 요소 조합이 포함될 수 있습니다. 디버거에서는 프로세스 및 컴퓨터 간의 실행 논리를 추적하여 현재 진행되고 있는 작업에 대한 논리 뷰를 제공할 수 있어야 합니다.

CLR 디버깅 API에서는 다중 프로세스 디버깅을 직접적으로 지원하지 않습니다. 반면 API를 사용하는 디버거에서는 이러한 지원을 직접적으로 제공하며 이를 수행하는 기존 메서드가 계속 작동합니다.

맨 위로 이동

API 범주

디버깅 API에는 다음과 같은 세 그룹의 인터페이스가 있으며 대개 이러한 인터페이스는 모두 CLR 디버거에 사용되고 비관리 코드로 구현됩니다.

  • CLR 응용 프로그램의 디버깅을 지원하는 인터페이스

  • 대개 PDB(프로그램 데이터베이스) 파일에 저장되는 기호 디버그 정보에 대한 액세스를 제공하는 인터페이스

  • 컴퓨터에서 프로세스 및 응용 프로그램 도메인 쿼리를 지원하는 인터페이스

디버깅 API는 다음 두 인터페이스 집합을 추가로 사용합니다.

  • 클래스 및 메서드 형식 정보와 같은 정적 프로그램 정보의 검사를 처리하는 메타데이터 API

  • 관리 코드 디버거에 대해 소스 수준 디버깅을 지원하는 기호 저장소 API

다음 표에 있는 기능 범주로 디버깅 인터페이스를 구성할 수도 있습니다.

API 범주

설명

등록

디버거에서 CLR에 등록하고, 특정 이벤트가 발생할 때 알림을 요청하기 위해 호출하는 인터페이스입니다.

Notification

CLR에서 다양한 이벤트를 디버거에 알리고 요청한 정보를 반환하기 위해 사용하는 콜백 인터페이스입니다. 이러한 인터페이스는 디버거를 통해 구현해야 합니다.

중단점

디버거에서 중단점에 대한 정보를 검색하기 위해 호출하는 인터페이스입니다.

실행

디버거에서 디버기 실행을 제어하고 호출 스택에 액세스하기 위해 호출하는 인터페이스입니다.

정보

디버거에서 디버기에 대한 정보를 가져오기 위해 호출하는 인터페이스입니다.

열거형

디버거에서 개체를 열거하기 위해 호출하는 인터페이스입니다.

수정

디버거에서 디버깅할 코드를 수정하기 위해 호출하는 인터페이스입니다.

다음 단원에서는 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 인수를 래퍼 함수에 제공할 수 있습니다.

맨 위로 이동

지원 환경

CLR에서 지원하는 모든 프로세서와 운영 체제에서 CLR 디버깅 기능을 사용할 수 있지만 다음과 같은 예외가 있습니다.

  • 64비트 운영 체제에서는 편집하며 계속하기와 혼합 모드 디버깅이 지원되지 않습니다. 64비트 운영 체제에서는 SetIP 메서드(ICorDebugILFrame::SetIPICorDebugNativeFrame::SetIP)에 대한 추가 제한 사항이 있습니다. 나머지 기능은 모든 프로세서에서 동일하며 포인터 크기, 레지스터 컨텍스트 등의 프로세서별 데이터 표현은 허용됩니다.

  • Win9x 기반 운영 체제에서는 편집하며 계속하기와 혼합 모드 디버깅이 지원되지 않습니다. 개별 기능에 대한 설명서에 나오는 몇 가지 구체적인 예외가 있지만 나머지 기능은 모든 운영 체제에서 동일합니다.

맨 위로 이동

관련 항목

제목

설명

CLR 디버깅 아키텍처

CLR 디버깅 API의 여러 구성 요소가 CLR 및 디버거와 상호 작용하는 방식에 대해 설명합니다.

.NET Framework 2.0의 디버깅 API 변경 내용

.NET Framework 버전 2.0의 디버깅에서 변경되거나 향상된 기능에 대해 설명합니다.

CorDebug.idl 인터페이스의 전제 조건

일부 CLR 디버깅 인터페이스에서 특정 상태로 디버깅되기 시작하는 프로세스를 요구하는 방법에 대해 설명합니다.

런타임 프로세스 디버깅

런타임 프로세스를 디버깅하는 방법에 대해 단계별로 설명합니다.

디버깅 중 프로그램 제어

디버거에서 CLR 디버깅 API를 사용하여 중단점을 설정하고, 관리 및 비관리 코드를 단계별로 실행하고, 예외를 처리하는 방법에 대해 설명합니다.

디버깅 중 프로그램 검사

디버거에서 CLR 디버깅 API를 사용하여 관리되는 스택 프레임에 액세스하고 식을 계산하는 방법에 대해 설명합니다.

디버깅 API를 사용하여 동적으로 코드 삽입

CLR에서 활성 스레드를 도용하여 원래의 PE 파일(이식 가능 파일)에는 없는 코드를 실행하는 동적 코드 삽입에 대해 설명합니다.

디버깅 API의 게시 프로세스

컴퓨터의 프로세스 및 응용 프로그램 도메인에 대한 정보를 열거하고 제공하는 CLR 프로세스 게시 인터페이스에 대해 요약합니다.

디버깅 API의 보안 고려 사항

CLR 디버깅 API를 사용할 때의 보안 고려 사항에 대해 설명합니다.

디버깅 Coclass

디버깅 API에 사용되는 관리되지 않는 coclass를 설명합니다.

디버깅 인터페이스

공용 언어 런타임에서 실행되는 프로그램의 디버깅을 처리하는 관리되지 않는 인터페이스에 대해 설명합니다.

디버깅 전역 정적 함수

디버깅 API에 사용되는 관리되지 않는 전역 정적 함수를 설명합니다.

디버깅 열거형

디버깅 API에 사용되는 관리되지 않는 열거형을 설명합니다.

디버깅 구조체

디버깅 API에 사용되는 관리되지 않는 구조체를 설명합니다.

맨 위로 이동