vc如何调试程序调试的步骤是什么详细步骤

酷勤网 C 程序员的那点事!
当前位置: >
浏览次数:次
难怪很多前辈说调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。&
我以前接触的程序大多是有比较成形的思路和方法,调试起来出的问题都比较小,最近这个是我自己慢慢摸索调试,接触了很多新的调试方法,并查了很多前辈的总结,受益匪浅,总结以前的和新的收获如下:VC调试篇设置为了调试一个程序,首先必须使程序中包含调试信息。一般情况下,一个从AppWizard创建的工程中包含的Debug Configuration自动包含调试信息,但是是不是Debug版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的Configuration中增加调试信息,包括Release版本。为了增加调试信息,可以按照下述步骤进行:
打开Project settings对话框(可以通过快捷键ALT+F7打开,也可以通过IDE菜单Project/Settings打开)
选择C/C++页,Category中选择general ,则出现一个Debug Info下拉列表框,可供选择的调试信息 方式包括:  
Project settings
没有调试信息
Line Numbers Only
目标文件或者可执行文件中只包含全局和导出符号以及代码行信息,不包含符号调试信息
C 7.0- Compatible
目标文件或者可执行文件中包含行号和所有符号调试信息,包括变量名及类型,函数及原型等
Program Database
创建一个程序库(PDB),包括类型信息和符号调试信息。
Program Database for Edit and Continue
除了前面/Zi的功能外,这个选项允许对代码进行调试过程中的修改和继续执行。这个选项同时使#pragma设置的优化功能无效
选择Link页,选中复选框&Generate Debug Info&,这个选项将使连接器把调试信息写进可执行文件和DLL
如果C/C++页中设置了Program Database以上的选项,则Link incrementally可以选择。选中这个选项,将使程序可以在上一次编译的基础上被编译(即增量编译),而不必每次都从头开始编译。
调试方法:
1、使用 Assert(原则:尽量简单) assert只在debug下生效,release下不会被编译。
2、防御性的编程
3、使用Trace4、用GetLastError来检测返回值,通过得到错误代码来分析错误原因5、把错误信息记录到文件中
位置断点(Location Breakpoint) &&大家最常用的断点是普通的位置断点,在源程序的某一行按F9就设置了一个位置断点。但对于很多问题,这种朴素的断点作用有限。譬如下面这段代码:
void CForDebugDlg::OnOK()
&&&&&& for (int i = 0; i & 1000; i++)&&& //A
&&&&&&&&&&&&& int k = i * 10 - 2; //B
&&&&&&&&&&&&& SendTo(k);&&&&&&&&& //C
&&&&&&&&&&&&& int tmp = DoSome(i); //D
&&&&&&&&&&&&& int j = i /&&& //E
&&执行此函数,程序崩溃于E行,发现此时tmp为0,假设tmp本不应该为0,怎么这个时候为0呢?所以最好能够跟踪此次循环时DoSome函数是如何运行的,但由于是在循环体内,如果在E行设置断点,可能需要按F5(GO)许多次。这样手要不停的按,很痛苦。使用VC6断点修饰条件就可以轻易解决此问题。步骤如下。 &&1 Ctrl+B打开断点设置框,如下图: Figure 1设置高级位置断点 &&2 然后选择D行所在的断点,然后点击condition按钮,在弹出对话框的最下面一个编辑框中输入一个很大数目,具体视应用而定,这里1000就够了。 &&3 按F5重新运行程序,程序中断。Ctrl+B打开断点框,发现此断点后跟随一串说明:...487 times remaining。意思是还剩下487次没有执行,那就是说执行到513(1000-487)次时候出错的。因此,我们按步骤2所讲,更改此断点的skip次数,将1000改为513。 &&4 再次重新运行程序,程序执行了513次循环,然后自动停在断点处。这时,我们就可以仔细查看DoSome是如何返回0的。这样,你就避免了手指的痛苦,节省了时间。 &&再看位置断点其他修饰条件。如Figure 1所示,在&Enter the expression to be evaluated:&下面,可以输入一些条件,当这些条件满足时,断点才启动。譬如,刚才的程序,我们需要i为100时程序停下来,我们就可以输入在编辑框中输入&i==100&。 &&另外,如果在此编辑框中如果只输入变量名称,则变量发生改变时,断点才会启动。这对检测一个变量何时被修改很方便,特别对一些大程序。 &&用好位置断点的修饰条件,可以大大方便解决某些问题。
数据断点(Data Breakpoint) &&软件调试过程中,有时会发现一些数据会莫名其妙的被修改掉(如一些数组的越界写导致覆盖了另外的变量),找出何处代码导致这块内存被更改是一件棘手的事情(如果没有调试器的帮助)。恰当运用数据断点可以快速帮你定位何时何处这个数据被修改。譬如下面一段程序:
#include &stdafx.h&
&int main(int argc, char* argv[])
&&&&&& char szName1[10];
&&&&&& char szName2[4];
&&&&&& strcpy(szName1,&shenzhen&);&&&&&&&&&&&&&
&&&&&& printf(&%s
&, szName1);&&&&&&&&& //A
&&&&&&& strcpy(szName2, &vckbase&);&&&&&&&&&&&&& //B
&&&&&& printf(&%s
&, szName1);
&&&&&& printf(&%s
&, szName2);
&&&&&&& return 0;
&&&&&&&&这段程序的输出是
&&&&& &&&&&& szName1: shenzhen
&&&&&& szName1: ase
&&&&&& szName2: vckbase
&&&& szName1何时被修改呢?因为没有明显的修改szName1代码。我们可以首先在A行设置普通断点,F5运行程序,程序停在A行。然后我们再设置一个数据断点。如下图: Figure 2 数据断点 &&F5继续运行,程序停在B行,说明B处代码修改了szName1。B处明明没有修改szName1呀?但调试器指明是这一行,一般不会错,所以还是静下心来看看程序,哦,你发现了:szName2只有4个字节,而strcpy了7个字节,所以覆写了szName1。 &&数据断点不只是对变量改变有效,还可以设置变量是否等于某个值。譬如,你可以将Figure 2中红圈处改为条件&szName2[0]==""""y""""&,那么当szName2第一个字符为y时断点就会启动。 &&可以看出,数据断点相对位置断点一个很大的区别是不用明确指明在哪一行代码设置断点。
其他调试手段:系统提供一系列特殊的函数或者宏来处理Debug版本相关的信息,如下:
宏名/函数名
使用方法和printf完全一致,他在output框中输出调试信息
它接收一个表达式,如果这个表达式为TRUE,则无动作,否则中断当前程序执行。对于系统中出现这个宏 导致的中断,应该认为你的函数调用未能满足系统的调用此函数的前提条件。例如,对于一个还没有创建的窗口调用SetWindowText等。
和ASSERT功能类似,所不同的是,在Release版本中,ASSERT不计算输入的表达式的值,而VERIFY计算表达式的值。
值WatchVC支持查看变量、表达式和内存的值。所有这些观察都必须是在断点中断的情况下进行。观看变量的值最简单,当断点到达时,把光标移动到这个变量上,停留一会就可以看到变量的值。VC提供一种被成为Watch的机制来观看变量和表达式的值。在断点状态下,在变量上单击右键,选择Quick Watch, 就弹出一个对话框,显示这个变量的值。单击Debug工具条上的Watch按钮,就出现一个Watch视图(Watch1,Watch2,Watch3,Watch4),在该视图中输入变量或者表达式,就可以观察 变量或者表达式的值。注意:这个表达式不能有副作用,例如++运算符绝对禁止用于这个表达式中,因为这个运算符将修改变量的值,导致 软件的逻辑被破坏。Memory由于指针指向的数组,Watch只能显示第一个元素的值。为了显示数组的后续内容,或者要显示一片内存的内容,可以使用memory功能。在 Debug工具条上点memory按钮,就弹出一个对话框,在其中输入地址,就可以显示该地址指向的内存的内容。VariblesDebug工具条上的Varibles按钮弹出一个框,显示所有当前执行上下文中可见的变量的值。特别是当前指令涉及的变量,以红色显示。寄存器Debug工具条上的Reigsters按钮弹出一个框,显示当前的所有寄存器的值。
调试技巧:
1、VC++中F5进行调试运行
a)、在output Debug窗口中可以看到用TRACE打印的信息
b)、 Call Stack窗口中能看到程序的调用堆栈
2、当Debug版本运行时发生崩溃,选择retry进行调试,通过看Call Stack分析出错的位置及原因
3、使用映射文件调试
a)、创建映射文件:Project settings中link项,选中Generate mapfile,输出程序代码地址:/MAPINFO: LINES,得到引出序号:/MAPINFO: EXPORTS。
b)、程序发布时,应该把所有模块的映射文件都存档。
c)、查看映射文件:见& 通过崩溃地址找出源代码的出错行&文件。
4、可以调试的Release版本
  Project settings中C++项的Debug Info选择为Program Database,Link项的Debug中选择Debug Info和Microsoft format。
5、查看API的错误码,在watch窗口输入@err可以查看或者@err,hr,其中&,hr&表示错误码的说明。
6、Set Next Statement:该功能可以直接跳转到指定的代码行执行,一般用来测试异常处理的代码。
7、调试内存变量的变化:当内存发生变化时停下来。???
进程控制VC允许被中断的程序继续运行、单步运行和运行到指定光标处,分别对应快捷键F5、F10/F11和CTRL+F10。各个快捷键功能如下:  
调试/继续运行
单步,如果涉及到子函数,不进入子函数内部
单步,如果涉及到子函数,进入子函数内部
运行到当前光标处。
设置断点/清除断点
Ctrl+Shift+F9
清除所有断点
Call Stack调用堆栈反映了当前断点处函数是被那些函数按照什么顺序调用的。单击Debug工具条上的Call stack就显示Call Stack对话框。在CallStack对话框中显示了一个调用系列,最上面的是当前函数,往下依次是调用函数的上级函数。单击这些函数名可以跳到对应的函数中去。
关注一个好的程序员不应该把所有的判断交给编译器和调试器,应该在程序中自己加以程序保护和错误定位,具体措施包括:
对于所有有返回值的函数,都应该检查返回值,除非你确信这个函数调用绝对不会出错,或者不关心它是否出错。
一些函数返回错误,需要用其他函数获得错误的具体信息。例如accept返回INVALID_SOCKET表示accept失败,为了查明 具体的失败原因,应该立刻用WSAGetLastError获得错误码,并针对性的解决问题。
有些函数通过异常机制抛出错误,应该用TRY-CATCH语句来检查错误
程序员对于能处理的错误,应该自己在底层处理,对于不能处理的,应该报告给用户让他们决定怎么处理。如果程序出了异常, 却不对返回值和其他机制返回的错误信息进行判断,只能是加大了找错误的难度。
另外:VC中要编制程序不应该一开始就写cpp/h文件,而应该首先创建一个合适的工程。因为只有这样,VC才能选择合适的编译、连接 选项。对于加入到工程中的cpp文件,应该检查是否在第一行显式的包含stdafx.h头文件,这是Microsoft Visual Studio为了加快编译 速度而设置的预编译头文件。在这个#include &stdafx.h&行前面的所有代码将被忽略,所以其他头文件应该在这一行后面被包含。对于.c文件,由于不能包含stdafx.h,因此可以通过Project settings把它的预编译头设置为&不使用&,方法是:
弹出Project settings对话框
Category选择Precompilation Header
选择不使用预编译头。
便于调试的代码风格:
不用全局变量
所有变量都要初始化,成员变量在构造函数中初始化
尽量使用const
详尽的注释
总结 &&调试最重要的还是你要思考,要猜测你的程序可能出错的地方,然后运用你的调试器来证实你的猜测。
& 相关主题:& & & & 《VC++程序调试》 - 即将更新 ~
作者/回复/查看
站长提醒 /2
本着让大家学习到更多更好的VC++编程技术,选择一个适合自己的方向发展下去。VC驿站从即日起招聘教程讲师,主要是VC++方向,可以涉及安全类、破解类、编程开发类等等。
期待您的加盟。。。
为了能给广大编程爱好者提供一个更好的学习交流平台,从即日起面向广大网友特举办《发原创得奖励》活动。Vip教程,驿站U盘,无线鼠标 免费送,礼品丰厚,赶快来参加吧!
VC驿站微信公众号cctry2009
Powered by Discuz! X3.2lm_onlyone 的BLOG
用户名:lm_onlyone
文章数:37
访问量:37189
注册日期:
阅读量:5863
阅读量:12276
阅读量:359743
阅读量:1055734
51CTO推荐博文
调试肯定在Debug模式中
由于DLL程序不能生成窗口等等原因不好调试,所以我们无法了解DLL程序的流程是怎么样的。下面简单介绍一个如何来调试DLL程序。
应该知道写DLL文件肯定是给某个应用程序使用的,如果没有程序用到它那它就没有存在的意义了。
既然知道DLL是给某个应用程序使用之后,那么如果应用程序开始运行了,在加载DLL后,必然会进入到DLL程序内部去,如果这个时候DLL程序中设了断点,而断点又是DLL程序运行必经之处,那么运行到这个地方,应该会停下来的。
那么调试是在应用程序中进行呢?还是DLL程序中进行呢?当然是DLL了 因为它就是我们调试的对象嘛。但必须要导入一个能够调用它的程序进来,通过应用程序的启动来达到调试的目的。
那么如何在DLL中设置应用程序呢?
很简单,打开VC 6.0 在vc里面打开要调试的DLL程序,点击菜单Project(中文版可能叫工程)-&setting(设置) 可以看到一个对话框,左边Setting For要选Win32 Debug模式,Setting For下面是一个树形列表,显示的所有工程信息,选择一个你要调试的工程(不需要打开选择下面的.h,.cpp文件)
右边点击Debug主要设置三个地方:
Catagory:General
Executable for debug session:这个目录很重要,这里就是选择应用程序了(这个应用程序必须要用到这个DLL文件) 比如说 你的DLL文件目录在E盘,而你的应用程序在C:\Test\Test.exe这里,那么这个目录就必须填写C:\Test\Test.exe。
Wroking directory:就是填写工作的目录,这里填的应用程序的工作目录就是C:\Test ,就是包含应用程序的目录
这样设置好了以后,就可以开始调试啦,你在DLL中设置断点,然后点击调试,可能会出现询问的一个窗口,不要选择那个勾,直接OK就可以了。然后应用程序出现后,你就可以模拟各种情况,来观察DLL中的行为了。
还要加一些内容:按F5调试的时候怎么输入命令行参数?
int&& main&& (int&& argc,&& char&& *argv[]);&& 就是这个argv,怎么才能输入?&
Project菜单中的&Settings&&,Debug选项卡,Program&& Arguments里边添写命令行参数。
了这篇文章
类别:┆阅读(0)┆评论(0)Visual Studio原生开发的10个调试技巧 - 文章 - 伯乐在线
& Visual Studio原生开发的10个调试技巧
【感谢 的热心翻译。如果其他朋友也有不错的原创或译文,可以尝试。】
最近碰巧读了Ivan Shcherbakov写的一篇文章,《》。这篇文章只介绍了一些有关Visual Studio的基本调试技巧,但是还有其他一些同样有用的技巧。我整理了一些Visual Studio(至少在VS 2008下)原生开发的调试技巧。(如果你是工作在托管代码下,调试器会有更多的特性,在CodeProject中有介绍它们的文章),下面是我的整理的一些技巧:
异常中断 | Break on Exception
Watch窗口中的伪变量 | Pseudo-variables in Watch Windows
符号越界后查看堆对象 |
查看数组的值
避免进入不必要的函数
从代码启动调试器 | Launch the debugger from code
在Output窗口打印
隔离内存泄漏
调试发行版 | Debug the Release Build
技巧1: 异常中断
在处理被调用之前,异常发生时可以 启动调试器进行中断,可以让你在异常发生后立即调试程序。操作调用栈便于你去查找异常发生的根本原因。
Vistual Studio允许你去指定想要中断的异常类型或者特殊异常。选择菜单Debug&Exceptions弹出对话框,你可以指定原生的(或者托管的)异常,除了调试器自带的一些默认异常,你还可以添加自己的自定义异常。
下面是一个std::exception 异常抛出时调试器中断的例子。
更多阅读:
技巧2:Watch窗口中的伪变量
Watch窗口或QuickWatch对话框提供一些特定的(调试器可识别的)变量,被称为伪变量。文档包含以下:
$tid—–当前线程的线程ID
$pid——进程ID
$cmdline———-启动程序的命令行字符串
$user———-正在运行程序的账户信息
$registername—–显示寄存器registername 的内容
不管怎么样,关于最后一个错误的伪变量是非常有用的:
$err——–显示最后一个错误的错误码
$err,hr—显示最后一个错误的错误信息
更多阅读:
技巧3:符合越界后查看堆对象
有时候,在调试符号越界后,你还想查看对象的值,这个时候,watch窗口中的变量是被禁用的,不能再查看(也不能更新),尽管对象仍然存在。你如果知道对象的地址,可以继续充分地观察它。你可以将地址转换为该对象类型的指针,放在watch窗中。
下面的例子中,当单步跳出do_foo()之后,_foo不能再被访问。但是,将它的地址转换为foo*后,就可以继续观察这个对象。
技巧4:查看数组的值
如果你在操作一个很大的数组(我们假设至少有几百个元素吧,但是可能更少),在Watch窗口中展开数组,查找一些特定范围内的元素很麻烦,因为你要不停地滚动.如果数组是分配在堆上的话,你甚至不能在watch窗口中展开数组元素.对此,有一个解决办法。你可以使用(array+ &offset&),&count& 去查看从&offset&位置开始的特定范围的&count&元素(当然,这儿的数组是你的实际对象)。如果想查看整个数组,可以简单使用array,&count&.
如果你的数组是在堆上,你可以在watch窗口中将它展开,但是要查看某个特定范围的值,用法稍有不同:((T*) array + &offset&),&count&(注意这种用法对于堆上的多维数组也有效)。但是这种情况下,T是指数组元素的类型。
如果你在用MFC,并使用其中的’array’容器,像 CArray, CDWordArray,CStringArray等等。你当然可以使用同样的过滤方法。除此之外,你必须查看array的m_pData成员,它是保存数据的真实缓存。
技巧5:避免进入不必要的函数
很多时候,你在调试代码时可能会进入到你想跳过的函数,像构造函数,赋值操作或者其他的。其中最困扰我的是CString构造函数。下面是一个例子,当你准备单步执行take_a_string()函数时,首先进入到CString的构造函数。
void take_a_string(CString const &text)
void test_string()
take_a_string(_T(&sample&));
void take_a_string(CString const &text){}&void test_string(){&& take_a_string(_T("sample"));}
幸运的是可以告诉调试器去跳过哪些方法,类或者整个命名空间。实现它的方法也已经改变了,回到使用VS6的日子,通常是通过autoexp.dat文件来指定的。Vistual Studio 2002改成了使用注册表设置。想要跳过一些函数,你需要在注册表里添加一些值(详情如下):
实际位置取决于你使用的Vistual Studio版本和操作系统平台(x86或x64,因为注册表只能在64位的Windows下浏览)
值的名字是数字,代表规则的优先级;数字越大,优先级越高。
值数据是一个正则表达式的REG_SZ值,用于指定怎样过滤和执行。
为了避免进入任何CString方法,我添加了下面的规则:
有了这个,即使你强制进入上例中的take_a_string(),调试器也会跳过CString的构造函数。
更多阅读:
技巧6:从代码启动调试器 Launch the debugger from code
你可能很少需要将调试器附加到程序中,但你不能在Attach窗口这样做(可能因为中断发生太快而没有捕获到),你也不能一开始就在调试器中启动程序。你可以在程序中产生中断给调试器一个机会通过调用内部的_degbugbreak()来附加。
void break_for_debugging()
__debugbreak();
void break_for_debugging(){&& __debugbreak();}
实际上还有其他的方法来完成,例如触发中断3,但这仅仅适用于x86平台(C++64位不再支持ASM)。另外还有DebugBreak()函数,但它的使用不怎么简便,所以这里推荐使用内部方法。
__asm int 3;
__asm int 3;
程序运行内部方法时会停止运行,这时你就有机会将调试器附加到该进程。
更多阅读:
技巧7:在output窗口打印
通过调用DebugOutputString可以在调试器的output窗口显示一段特定的文本。如果没有附加的调试器,该函数什么也不做。
更多阅读:
技巧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.
& CD CD CD CD CD CD CD CD
Object dump complete.
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 Object dump complete.
在一个特定的(可复现的)位置中断的步骤如下:
确定你有足够的关于内存泄漏的报告模式(参考 使用CRT库检测内存泄漏)
多次运行程序直到你能在程序运行结束后的内存泄漏报告里找到一个可复现的分配编号,例如上个例子中的(341)
在程序一开始的地方设置一个断点以便你能够尽早地进行中断。
当最初的中断发生时,watch窗口的Name栏里会显示:{,,msvcr90d.dll}_crtBreakAlloc,在Value栏里写入你想要查找的位置编号
继续调试(F5)
程序执行到指定位置会停止,你可以使用调用栈被指引找到被该位置触发的那段代码。
遵循这些步骤, 在上个例子中,使用分配的编号(341)就可以识别内存泄漏的起因。
技巧9:调试发行版
调试和发布是两个不同的目的。调试配置是用于开发的,而发布配置,顾名思义,是用来作为程序的最终版本,因为它必须严格遵循发布的质量要求,该配置包含优化部分和调试版本的中断调试的设置。而且,有时候,要像调试调试版本一样去调试发行版。要做到这一点,你需要在配置里做一些改变。但是这种情况下,你就不再是在调试发行版,而是调试和发行的混合版。
你还应该做一些事儿,以下是必须要做的:
配置C/C++ &General&Debug Information Format 应该为 “Program Database(/Zi)”
配置C/C++ &Optimization&Optimization 应该为”Disabld(/Od)”
配置Linker&Debugging&Generate Debug Info 应该为”Yes/(DEBUG)”
如图所示:
更多阅读:
技巧10:远程调试
另一个重要的调试就是远程调试,这是一个更大的话题,多次被提到,这里我只做一下简单的概括:
你需要在远程机器上安装远程调试监控
远程调试监控必须以管理员身份运行,并且用户必须属于管理员组
在你运行监控时,会开启一个新的服务,该服务的名字必须用Visual Studio的Attach to Progress窗口的Qualifier组合框的值。
远程和本地机器上的防火墙必须允许Visual Studio和远程调试监控之间能够通信
想要调试,PDB文件是关键;为了能够让VisualStudio自动加载它们,必须满足以下条件:
1)本地的PDB文件必须可用(在远程机器的相同路径下放置一个对应的模块)。
2) 远程机器上的托管PDB文化必须可用。
远程调试监控下载:
更多阅读:
Ivan Shcherbakov那篇文章和我这篇文章提到的调试技巧,在大多数的调试问题中都是必不可少的。想要知道更多的关于调试技巧的知识,建议阅读文章中提供的额外阅读。
关于作者:
可能感兴趣的话题
为毛神马东东上了CSDN就会多一个哗众取宠,牛BB哄哄的名称捏。。。
关于伯乐在线博客
在这个信息爆炸的时代,人们已然被大量、快速并且简短的信息所包围。然而,我们相信:过多“快餐”式的阅读只会令人“虚胖”,缺乏实质的内涵。伯乐在线内容团队正试图以我们微薄的力量,把优秀的原创文章和译文分享给读者,为“快餐”添加一些“营养”元素。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2016 伯乐在线3914人阅读
技术资料(82)
日记博文(53)
&调试是一个程序员最基本的技能,其重要性甚至超过学习一门语言。不会调试的程序员就意味着他即使会一门语言,却不能编制出任何好的软件。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3409540次
积分:36978
积分:36978
排名:第85名
原创:438篇
转载:393篇
评论:1079条
(3)(1)(3)(3)(1)(1)(1)(3)(3)(1)(2)(1)(3)(2)(1)(7)(2)(2)(2)(4)(2)(4)(7)(1)(1)(21)(16)(3)(2)(3)(1)(3)(2)(7)(10)(5)(6)(7)(12)(3)(7)(7)(15)(9)(9)(18)(21)(7)(9)(7)(8)(44)(10)(26)(5)(2)(1)(7)(12)(1)(2)(1)(3)(7)(11)(10)(2)(3)(1)(1)(1)(9)(7)(3)(7)(1)(2)(5)(3)(1)(13)(92)(103)(25)(2)(57)(26)(4)(45)

我要回帖

更多关于 vc如何调试程序 的文章

 

随机推荐