>  기사  >  백엔드 개발  >  Visual Studio 네이티브 개발을 위한 10가지 디버깅 팁 공유

Visual Studio 네이티브 개발을 위한 10가지 디버깅 팁 공유

高洛峰
高洛峰원래의
2017-02-07 10:56:011541검색

이 문서에서는 Visual Studio에 대한 몇 가지 기본적인 디버깅 팁만 다루고 있지만 똑같이 유용한 다른 팁도 있습니다. Visual Studio(적어도 VS 2008 이하)에서 네이티브 개발을 위한 몇 가지 디버깅 팁을 정리했습니다. (관리되는 코드에서 작업하는 경우 디버거에는 더 많은 기능이 있으며 CodeProject에 해당 기능을 소개하는 기사가 있습니다.) 다음은 제가 정리한 몇 가지 팁입니다.

예외 발생 시 중단 | Watch Windows | 코드에서 디버거 실행
출력 창에서 인쇄
메모리 누수 격리
릴리스 버전 디버그 🎜>
핸들러가 호출되기 전에 디버거를 시작하여 중단할 수 있습니다. 예외가 발생하면 예외가 발생한 직후에 프로그램을 디버그할 수 있습니다. 호출 스택을 조작하면 예외의 근본 원인을 찾을 수 있습니다.

Visual Studio를 사용하면 중단하려는 예외 유형이나 특수 예외를 지정할 수 있습니다. 디버그>예외 메뉴를 선택하면 대화 상자가 나타납니다. 디버거와 함께 제공되는 일부 기본 예외 외에도 사용자 정의 예외를 추가할 수도 있습니다.




다음은 std::Exception 예외가 발생했을 때 디버거가 중단되는 예입니다.




팁 2: 조사식 창의 의사 변수

조사식 창 또는 QuickWatch 대화 상자는 다음과 같은 몇 가지 특정(디버거 인식 가능) 변수를 제공합니다. 더미 변수라고 합니다. 문서에는 다음이 포함됩니다. 分享Visual Studio原生开发的10个调试技巧

$tid——현재 스레드의 스레드 ID

$pid——프로세스 ID

$cmdline——프로그램을 시작하는 명령줄 문자열

$user — ——-실행 중인 프로그램의 계정 정보 分享Visual Studio原生开发的10个调试技巧$registername——-레지스터의 내용 표시 Registername

어쨌든 마지막 오류에 대한 의사 변수는 매우 유용합니다:


$err —— – 마지막 오류의 오류 코드 표시
$err, hr—마지막 오류의 오류 메시지 표시




팁 3: 이후 힙 개체 확인 범위 초과

때때로 디버그 기호가 범위를 벗어난 후에도 개체의 값을 보고 싶은 경우 조사식 창의 변수가 비활성화되어 더 이상 볼 수 없습니다( 또는 업데이트됨), 개체는 여전히 존재합니다. 물체의 주소를 알면 계속해서 완전히 관찰할 수 있습니다. 주소를 이 개체 유형의 포인터로 변환하여 Watch 창에 넣을 수 있습니다.

다음 예에서는 do_foo()를 벗어나면 _foo에 더 이상 액세스할 수 없습니다. 그러나 주소를 foo*로 변환한 후에는 이 객체를 계속해서 관찰할 수 있습니다.

分享Visual Studio原生开发的10个调试技巧

팁 4: 배열 값 보기


매우 큰 배열로 작업하는 경우(최소 수백 개의 요소가 있다고 가정하지만 가능하지 않음) 특정 범위의 요소를 찾기 위해 Watch 창에서 배열을 확장하는 것은 계속 스크롤해야 하기 때문에 번거롭습니다. 배열이 힙에 할당된 경우 Watch에서 배열 요소를 확장할 수도 없습니다. window.Right 따라서 해결책이 있습니다. (array+ ab76cfca1a1dc7ff1291dcdf873f72ec),570b78fce6f4d82c6d7725059f1f48f1를 사용하면 ab76cfca1a1dc7ff1291dcdf873f72ec에서 시작하는 특정 범위의 570b78fce6f4d82c6d7725059f1f48f1 요소를 볼 수 있습니다(물론 배열은 실제 개체입니다). 전체 배열을 보려면 array,570b78fce6f4d82c6d7725059f1f48f1를 사용하면 됩니다.


배열이 힙에 있는 경우 시계에서 확장할 수 있습니다. 그러나 특정 범위의 값을 보려면 사용법이 약간 다릅니다: ((T*) 배열 + ab76cfca1a1dc7ff1291dcdf873f72ec),570b78fce6f4d82c6d7725059f1f48f1 ). 하지만 이 경우 T는 배열 요소의 유형을 나타냅니다. 分享Visual Studio原生开发的10个调试技巧

分享Visual Studio原生开发的10个调试技巧

MFC를 사용하고 CArray, CDWordArray, CStringArray 등과 같은 '배열' 컨테이너를 사용하는 경우 물론 동일한 필터링 방법을 사용할 수 있습니다. 그 외에도 데이터를 보유하는 실제 캐시인 배열의 m_pData 멤버를 살펴봐야 합니다.

分享Visual Studio原生开发的10个调试技巧

팁 5: 불필요한 함수 입력을 피하세요

코드를 디버깅할 때 생성자, 할당 등 건너뛰고 싶은 함수를 입력하는 경우가 많습니다. 작동 또는 기타. 나를 가장 괴롭히는 것은 CString 생성자입니다. 다음은 take_a_string() 함수를 실행할 준비가 되면 먼저 CString 생성자를 입력합니다.

void take_a_string(CString const &text){}void test_string(){ take_a_string(_T("sample"));}

分享Visual Studio原生开发的10个调试技巧

다행히도 알 수 있습니다 어떤 메서드, 클래스 또는 전체 네임스페이스를 건너뛸 디버거입니다. 이를 수행하는 방법도 변경되었습니다. VS6 시절에는 일반적으로 autoexp.dat 파일을 통해 지정되었습니다. Visual Studio 2002는 레지스트리 설정을 사용하도록 변경되었습니다. 일부 기능을 건너뛰려면 레지스트리에 일부 값을 추가해야 합니다(자세한 내용은 아래 참조).

실제 위치는 사용 중인 Vistual Studio 버전과 운영 체제 플랫폼(x86 또는 x64, 레지스트리는 64비트 Windows에서만 검색할 수 있습니다.) 값 이름은 규칙의 우선순위를 나타내는 숫자입니다. 숫자가 클수록 우선순위가 높습니다. 값 데이터는 필터링 및 실행 방법을 지정하는 정규식의 REG_SZ 값입니다.

CString 메소드 입력을 피하기 위해 다음 규칙을 추가했습니다.

分享Visual Studio原生开发的10个调试技巧

이를 통해 위의 예에서 take_a_string()을 강제로 실행하더라도, 디버거는 CString의 생성자도 건너뜁니다.

팁 6: 코드에서 디버거 시작

프로그램에 디버거를 연결할 필요가 거의 없지만 연결 창에서는 연결할 수 없습니다(인터럽트가 너무 빨리 발생하기 때문일 수 있음). 잡히면) 처음에는 디버거에서 프로그램을 시작할 수도 없습니다. 내부적으로 _degbugbreak()를 호출하여 디버거에 연결할 기회를 제공하기 위해 프로그램에서 중단을 생성할 수 있습니다.

void break_for_debugging() {
__debugbreak();
}

실제로 인터럽트 3을 트리거하는 등의 다른 방법이 있지만 이는 x86 플랫폼에서만 작동합니다(ASM은 더 이상 C++ 64비트에서 지원되지 않습니다). DebugBreak() 함수도 있는데 사용법이 그리 쉽지 않으니 여기서는 내부 메소드를 사용하는 것을 추천한다.

__asm int 3;

내부 메서드를 실행하면 프로그램 실행이 중지됩니다. 이때 디버거를 프로세스에 연결할 수 있습니다.

分享Visual Studio原生开发的10个调试技巧

分享Visual Studio原生开发的10个调试技巧

分享Visual Studio原生开发的10个调试技巧

팁 7: 출력 창에서 인쇄

할 수 있습니다 DebugOutputString을 호출하여 디버거의 출력 창에 특정 텍스트를 표시합니다. 연결된 디버거가 없으면 이 함수는 아무 작업도 수행하지 않습니다.

分享Visual Studio原生开发的10个调试技巧

技巧8:隔离内存泄漏 

内存泄漏是在原生开发中的一个很重要的问题,要检测内存泄漏是一个很严峻的挑战,尤其是在大型项目中。Vistual Studio可以提供检测内存泄漏的报告,还有其他的一些应用程序(免费的或商业的)也可以帮助你检测内存泄漏.有些情况下,在一些内存分配最终会导致泄漏时,可以使用调试器去中断。但是你必须找到可再现的分配编号(尽管没那么容易)。如果能做到这一点,执行程序时调试器才会中断。 

我们来看下面的代码,分配了8个字节,却一直没释放分配的内存。Visual Studio提供了造成内存泄漏的对象的报告,多运行几次,会发现一直是同一个分配编号(341)。 

void leak_some_memory() 
{ 
char* buffer = new char[8]; 
} 
Dumping objects -> 
d:\marius\vc++\debuggingdemos\debuggingdemos.cpp(103) : {341} normal block at 0x00F71F38, 8 bytes long. 
Data: < > CD CD CD CD CD CD CD CD

在一个特定的(可复现的)位置中断的步骤如下: 

确定你有足够的关于内存泄漏的报告模式(参考 使用CRT库检测内存泄漏) 
多次运行程序直到你能在程序运行结束后的内存泄漏报告里找到一个可复现的分配编号,例如上个例子中的(341) 
在程序一开始的地方设置一个断点以便你能够尽早地进行中断。 
当最初的中断发生时,watch窗口的Name栏里会显示:{,,msvcr90d.dll}_crtBreakAlloc,在Value栏里写入你想要查找的位置编号 
继续调试(F5) 
程序执行到指定位置会停止,你可以使用调用栈被指引找到被该位置触发的那段代码。 
遵循这些步骤, 在上个例子中,使用分配的编号(341)就可以识别内存泄漏的起因。 

分享Visual Studio原生开发的10个调试技巧

技巧9:调试发行版 

调试和发布是两个不同的目的。调试配置是用于开发的,而发布配置,顾名思义,是用来作为程序的最终版本,因为它必须严格遵循发布的质量要求,该配置包含优化部分和调试版本的中断调试的设置。而且,有时候,要像调试调试版本一样去调试发行版。要做到这一点,你需要在配置里做一些改变。但是这种情况下,你就不再是在调试发行版,而是调试和发行的混合版

分享Visual Studio原生开发的10个调试技巧

你还应该做一些事儿,以下是必须要做的: 

配置C/C++ >General>Debug Information Format 应该为 “Program Database(/Zi)” 
配置C/C++ >Optimization>Optimization 应该为”Disabld(/Od)” 
配置Linker>Debugging>Generate Debug Info 应该为”Yes/(DEBUG)” 
如图所示: 

分享Visual Studio原生开发的10个调试技巧

技巧10:远程调试 

另一个重要的调试就是远程调试,这是一个更大的话题,多次被提到,这里我只做一下简单的概括: 

你需要在远程机器上安装远程调试监控 
远程调试监控必须以管理员身份运行,并且用户必须属于管理员组 
在你运行监控时,会开启一个新的服务,该服务的名字必须用Visual Studio的Attach to Progress窗口的Qualifier组合框的值。 

分享Visual Studio原生开发的10个调试技巧

分享Visual Studio原生开发的10个调试技巧

远程和本地机器上的防火墙必须允许Visual Studio和远程调试监控之间能够通信

想要调试,PDB文件是关键;为了能够让VisualStudio自动加载它们,必须满足以下条件:

1)本地的PDB文件必须可用(在远程机器的相同路径下放置一个对应的模块)。

 2) 远程机器上的托管PDB文化必须可用。

结束语 

Ivan Shcherbakov那篇文章和我这篇文章提到的调试技巧,在大多数的调试问题中都是必不可少的。

更多分享Visual Studio原生开发的10个调试技巧相关文章请关注PHP中文网!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.