C++编程的调试技巧97611.ppt_第1页
C++编程的调试技巧97611.ppt_第2页
C++编程的调试技巧97611.ppt_第3页
C++编程的调试技巧97611.ppt_第4页
C++编程的调试技巧97611.ppt_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C+编程的调试技巧,主要内容,VC+集成开发环境 调试方法 如何独立解决问题 编程规范,一、集成开发环境的熟悉,保存、全部保存,打开最近的工程,给工程中添加文件,查找文件,在指定目录下的某类型文件中搜索所有包含某字符串的文件,Debug:带有调试信息,文件大。 Release:没有调试信息,不能调试,文件小,切换Debug模式和Release模式,比较文件大小,编译(ctrl+F7):编译源文件到目标文件 构建(F7):链接目标文件和库函数为可执行文件,如无目标文件则先生成 清洁:删掉debug或者release版本的所有中间文件和可执行文件 调试 单步执行(F10):单步执行,遇到函数调用时

2、把其当作一条语句执行 深入函数的单步执行(F11):单步执行,遇到函数调用是深入到其内部 执行到光标处(ctrl+F10):一次执行完光标前的所有语句,并停到光标处 跳出(shift+F11):执行完当前函数的所有剩余代码,并从函数跳出 重新开始调试(ctrl+shift+F5):重新开始调试过程 结束调试(shift+F5):执行完程序的剩余部分,结束调试 设置/取消断点(F9):在某一行设置和取消断点,当前执行的语句,堆栈的内容:函数调用关系,从这里可以 查看内存数据,程序执行过程中的一 些变量会显示在这里,著名的watch窗口:看变量 表达式、地址等各种信息,寄存器当前值,二、调试方法,

3、树立正确的编程方法论,没有解决不了的问题,树立编程信心 按照正确的方法来编程 从实践中体会解决问题的思路、编程的思想 熟练掌握语法,数据结构,算法、模式,底层环境 按照编程规范来编写代码 充分利用各种资源: 调试器 msdn 网络搜索引擎,常用调试手段,利用编译器的输出信息排除错误 利用调试器的调试功能 单步、run to cursor、断点、条件断点、查看堆栈、 利用watch窗口查看变量、表达式的值 分段调试法、增量调试法 利用flush人为刷新缓冲区 修改输出信息,增加标志位 利用输出语句打印调试信息 通过堆栈观察函数调用情况 综合程序调试方法 注释的技巧、条件编译,几个简单例子,#in

4、clude #include void main() cout=1;j/=2)if(d/j=1)cout1;if(d/j=0) cout0;d=d%j;coutsetw(10)octisetw(10)hexiendl; ,一个编程风格非常糟糕的例子:,/*FILE COMMENT* * System Name : for eduction (NO TRANSFERRING) * File Name : e05b.c * Contents : embedded C language entrance course * : exercise 5B: program using pointer *

5、: 乮pass one-dimensional array to function) * Model : for OAKS8-LCD Board * CPU : R8C/Tiny series * Compiler : NC30WA(V.5.30 Release 1) * OS : not be used * Programmer : RENESAS Semiconductor Training Center * Note : for OAKS8-R5F21114FP(R8C/11 group,20MHz) * * COPYRIGHT(C) 2004 RENESAS TECHNOLOGY CO

6、RPORATION * AND RENESAS SOLUTIONS CORPORATION ALL RIGHTS RESERVED * * History : *FILE COMMENT END*/ /* include file */ #include defs.h/* define common symbol */ #include oaks8lib.h/* for function to deal with OAKS8-LCDBoard peripheral*/ /* define function prototype */ int main(void); static void get

7、_string(unsigned char *message, unsigned char *buff); /* input string*/ static int get_strlength(unsigned char *str);/* get string length */ static void print_dec(unsigned char *message, int dec); /* display decimal number in LCD*/ /*FUNC COMMENT* * ID : 1.0 * function name : main * function : call

8、function to get string length, display result * parameter : none * return : result 0:normal end * function used : get_strlength * notice : none * History : *FUNC COMMENT END*/ int main(void) unsigned char buff10+1; /* define variable to save string input from key matrix*/ int count;/* define variabl

9、e for save number of character */ while(1) /* input string from key matrix */ get_string(Str=, buff); /* call function to get string length */ /* pass address of array saving string, get string length */ count = get_strlength(buff); /* display string length in LCD */ print_dec(Len=, count); return 0

10、; /*FUNC COMMENT* * ID : 1.1 * function name : get_string * function : input string from key matrix * parameter : message:pointer to input waiting message * : buff :pointer to space saving string input * return : none * function used : none * notice : none * History : *FUNC COMMENT END*/ static void

11、 get_string(unsigned char *message, unsigned char *buff) /* define function to input string*/ LCD_puts(message);/* display message*/ SW_gets(buff); /* input string from key matrix*/ LCD_puts(buff);/* display string input */ LCD_putchar(n);/* return */ /*FUNC COMMENT* * ID : 1.2 * function name : get

12、_strlength * function : refer string using pointer passed as argument, return length * parameter : str:address of string to count length * return : length * function used : none * notice : none * History : *FUNC COMMENT END*/ static int get_strlength(unsigned char *str) /* define function to get str

13、ing length*/ int len = 0;/* define and initialize variable for string length*/ /* refer every character in one-dimensional array buff pointed by */ /* pointer str, count up until detect (0) at end of string */ while(0 != *str+) len+;/* count number of character */ return len; /* return length*/ /*FU

14、NC COMMENT* * ID : 1.3 * function name : print_dec * function : display decimal number in LCD * parameter : message:pointer to input waiting message * : dec :decimal number to be displayed * return : none * function used : none * notice : none * History : *FUNC COMMENT END*/ static void print_dec(un

15、signed char *message, int dec) /* define function to display decimal number in LCD*/ LCD_puts(message);/* display message*/ LCD_putdec(dec);/*display decimal number in LCD*/ LCD_putchar(n);/* return */ /* end of file */,一个编程风格良好的例子:,结 论 1,永远不要写过长的语句,应该让代码尽可能简单;永远不要把两条语句写在一行中,以便于调试。,#include void mai

16、n() float num1,num2,outcome; char op,a; do coutnum1num2endl; coutopendl; if(num2!=0) switch(op) case *:outcome=num1*num2;break; case /:outcome=num1/num2;break; case +:outcome=num1+num2;break; case -:outcome=num1-num2;break; default:coutaendl; while(a=y); ,两个数的算术运算,/如果输入字符a,则显示1,否则程序结束 #include int f

17、() char c; coutc; if(c=a) return 1; else ; int main() coutf()endl; return 0; ,根据输入给出输出,结 论 2,要尽可能的熟悉语法知识 充分利用编译器提供的信息 编程过程中要细心 思路要清晰,没把握时,要先画流程图,然后再编码,#include int main() double a, b, c, d; coutabc; if(a=b ,判断三角形的形状,结 论 3,要掌握编程的本质: 是由程序员控制机器,使其按照我们的思路运转,机器本身没有智能。,#include void main() double integer1

18、,integer2,e,f,g,h; char op,a; cinop; coutinteger1; coutinteger2; switch(op). e=integer1+integer2; f=integer1-integer2; g=integer1*integer2; h=integer1/integer2; case +:coute; break; case -:coutf; break; case *:coutg; break; case /:couth; break; coutDo you want to continue(Y/N or y/n)?; ,两个数的算术运算,#in

19、clude void main() double integer1,integer2,e,f,g,h; char op,a; cinop; coutinteger1; coutinteger2; switch(op)./点 e=integer1+integer2;/这段代码执行不到 f=integer1-integer2; g=integer1*integer2; h=integer1/integer2; case +:coute; break; case -:coutf; break; case *:coutg; break; case /:couth; break; cout“Do you

20、 want to continue(Y/N or y/n)?”; /标记控制重复 ,两个数的算术运算,结 论 4,编译器不一定能给出确切的错误信息,要合理的“猜测” 出错信息 通过单步运行的方式加深我们对程序执行流程的理解。 单步执行是最重要的调试手段!,#include int main() char type = s; while(type != !) couttype; if (type = 65 ,判断一个字符是什么类别,另一个通过单步执行调试的例子,#include int main() char type = s; while(type != !) couttype; if (ty

21、pe = 65 ,判断一个字符是什么类别,通过单步执行可以搞清程序的执行线路,以发现错误点,#include int main() int m; coutm; for(int i=1;i=m-1;i+) m=m*i; cout阶乘为:mendl; return 0; ,求阶乘,#include int main() int m; coutm; for(int i=1;i=m-1;i+) m=m*i;/循环体内修改了循环条件 cout阶乘为:mendl; return 0; ,求阶乘,通过单步执行可以监视变量的变化,当变量与预期不一致是,即找到了错误点,#include int main() i

22、nt m; coutm; int n=m; for(int i=1;i=n-1;i+) m=m*i; cout阶乘为:mendl; return 0; ,求阶乘,结 论 5,通过单步执行可以发现程序运行的轨迹 通过单步执行可以随时监视变量的值,无论何时发现变量值与我们的预期不一致时,即找到了错误点,单步调试方法,前提:debug版本可执行程序,build正确 进入调试状态 F10为单步调试,要深入到子函数中单步调试,应在函数调用语句处按F11 单步调试应该结合watch窗口监视变量值的变化,稍复杂的例子,#include void main() for(int i=1;i=11-s;n-) c

23、out*;coutendl; coutendl; for(int z=1;z=10;z+) for(int p=9;p=10-z;p-) cout ; for(int q=1;q=z;q+) cout*;coutendl; coutendl; ,输出星号,#include void main() for(int i=1;i=11-s;n-) cout*;coutendl; coutendl; for(int z=1;z=10;z+) for(int p=9;p=10-z;p-) cout ; for(int q=1;q=z;q+) cout*;coutendl; coutendl; ,输出星号

24、,分析:程序比较长,输出怪异,一时难以发现出错地点,所以采用化整为零、化繁为简的分段调试法,#include void main() for(int i=1;i=11-s;n-) cout*;coutendl; coutendl; for(int z=1;z=10;z+) for(int p=9;p=10-z;p-) cout ; for(int q=1;q=z;q+) cout*;coutendl; coutendl; ,输出星号,使用到的调试方法: 分段调试 单步F10调试 run to cursor 强制输出(flush) 用watch窗口观察表达式的值,#include void ma

25、in() for(int i=1;i=z;p-) cout flush; for(int q=1;q=z;q+) cout*flush; coutendl; coutendl; ,调试后的程序,改正了循环中的逻辑问题,另外,本程序存在变量定义过多的缺点,#include void main() for(int i=1;i=11-s;n-) cout*;coutendl; coutendl; for(int z=1;z=10;z+) for(int p=9;p=10-z;p-) cout ; for(int q=1;q=z;q+) cout*;coutendl; coutendl; ,输出星号,

26、对错误程序的进一步分析: 为什么会出现黑屏?错误 原因在哪里?可通过修改 源代码,设置标志位来验证,结 论 6,分段调试:可以有效降低调试难度,快速定位错误的大致范围,“粗调” 单步F10调试:找到可疑点后,逐行执行可疑点附近的代码,对错误“精调” run to cursor:使程序快速运行到可疑点后暂停,克服F10运行速度慢的缺点 强制输出(flush):增加有参考价值的信息 watch窗口:可观察变量或表达式的值,配合F10进行单步“精调”,小技巧,在循环体内,每执行一次run to cursor,就相当于完整的执行了一遍循环体,经常用来替代多次执行F10。,/例 求阶乘 #include

27、 int Factorial ( int ) ; void main () int k ; cout k ; cout k ! = Factorial(k) endl ; int Factorial ( int n ) if ( n = 0 ) return 1 ; else return n * Factorial ( n - 1 ) ; ,分析程序执行流程,求阶乘,/例 求阶乘 #include int Factorial ( int ) ; void main () int k ; cout k ; cout k ! = Factorial(k) endl ; int Factorial

28、 ( int n ) if ( n = 0 ) return 1 ; else int m = n * Factorial ( n - 1 ); return m; ,简化return语句,求阶乘,/例 求阶乘 #include int Factorial ( int ) ; void main () int k ; cout k ; cout k ! = Factorial(k) endl ; int Factorial ( int n ) if ( n = 0 ) return 1 ; else coutthe parameter of this call is: nendl; int m

29、 = n * Factorial ( n - 1 ); coutlast call go back here: nendl; return m; ,增加调试输出信息,求阶乘,结 论 7,F11可以深入到函数内部单步执行,F11和F10结合起来使用可以调试多函数的程序。 step over可以从当前函数中跳出到调用点 观察堆栈能看到函数之间的调用关系 在适当的位置插入输出语句,有助于了解程序的执行流程,是一种十分重要的调试手段,小技巧,单步调试时,如果某条语句不是调用自定义的函数,那么不要按F11,尤其是本行包含了cout,/例 求菲波那契数列的第五项 #include int Fibonacc

30、i ( int n ) if ( n = 2 ) return 1 ; else return Fibonacci ( n-1 ) + Fibonacci ( n-2 ) ; void main () cout Fibonacci(5) endl ; ,求菲波那契数列第五项,请大家注意观察堆栈的变化,综合实例,#include #include #include int main() int m,i,k,n=0; bool prime=1; for(m=101;m=199;m+=2) k=int(sqrt(m); for(i=2;i=k;i+) if(m%i=0) prime=0; break

31、; if(prime) coutsetw(5)m; n+; if(n%10=0) coutendl; coutendlthe total number is: nendl; return 0; ,求100-200间的素数,#include #include #include int main() int m,i,k,n=0; bool prime=1; for(m=101;m=199;m+=2) k=int(sqrt(m); for(i=2;i=k;i+) if(m%i=0) prime=0; break; if(prime) coutsetw(5)m; n+; if(n%10=0) cout

32、endl; coutendlthe total number is: nendl; return 0; ,求100-200间的素数,用断点来代替run to cursor,在光标处设置断点F9,运行程序至断点处F5,光标放到第23行,设置条件断点,第23行的有效断点,第25行的无效断点,越过了前两次循环,停到了第三次,#include #include #include int main() int m,i,k,n=0; bool prime ; for(m=101;m=199;m+=2) prime=1; k=int(sqrt(m); for(i=2;i=k;i+) if(m%i=0) prime=0; break; if(prime) coutsetw

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论