VisualC60中的调试工具使用及常见错误.docx
- 文档编号:10515833
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:18
- 大小:296.25KB
VisualC60中的调试工具使用及常见错误.docx
《VisualC60中的调试工具使用及常见错误.docx》由会员分享,可在线阅读,更多相关《VisualC60中的调试工具使用及常见错误.docx(18页珍藏版)》请在冰点文库上搜索。
VisualC60中的调试工具使用及常见错误
C语言常见错误及解决方法
(注:
红色粗体是常见的错误,请大家检查自己的程序,并注意尽量不要犯这些常见的错误。
其余它体是避免错误的方法和正确的写法)
一、基础知识和数据类型、表达式
1、拼写错误,尤其是include,main,void,float等词。
C语言的32个关键字与基本含义如下:
double:
声明双精度变量或函数
int:
声明整型变量或函数
char:
声明字符型变量或函数
float:
声明浮点型变量或函数
void:
声明函数无返回值或无参数,声明无类型指针(基本上就这三个作用)
auto:
声明自动变量一般不使用
struct:
声明结构体变量或函数
break:
跳出当前循环
else:
条件语句否定分支(与if连用)
long:
声明长整型变量或函数
switch:
用于开关语句
case:
开关语句分支
enum:
声明枚举类型
register:
声明积存器变量
typedef:
用以给数据类型取别名(当然还有其他作用)
extern:
声明变量是在其他文件正声明(也可以看做是引用变量)
return:
子程序返回语句(可以带参数,也看不带参数)
union:
声明联合数据类型
const:
声明只读变量
short:
声明短整型变量或函数
unsigned:
声明无符号类型变量或函数
continue:
结束当前循环,开始下一轮循环
for:
一种循环语句(可意会不可言传)
signed:
生命有符号类型变量或函数
default:
开关语句中的“其他”分支
goto:
无条件跳转语句
sizeof:
计算数据类型长度
volatile:
说明变量在程序执行中可被隐含地改变
do:
循环语句的循环体
while:
循环语句的循环条件
static:
声明静态变量
if:
条件语句
2、{},[],(),‘’,“”不配对。
解决这个问题最好的方法就是每当写这些符号的时候就先写成一对,然后再在中间加内容。
3、忘记在语句的末尾加分号,或在预处理命令后多加分号。
记住:
每一个语句的后边都要加分号,而预处理命令并不是语句,所以不加分号,他们必须每行一条,不能把多个命令写在一行。
4、混淆/和\;注释对应的符号是/**/,而转义字符是以\开头,除号是/。
5、printf()和scanf()的参数设置有误,主要表现在以下几方面:
●类型不匹配的问题。
(例如:
有floata=3.5,但输出的时候printf(“a=%d”,a);则屏幕上会显示出a=0.00000或者提示其它运行错误)。
基本原则是:
float对应%f,int对应%d,char对应%c。
●个数不匹配。
无论是哪个函数,都可以有n个参数,第一个永远是“”括起来的内容,表示输出格式。
剩下的n-1个是输出的变量或者输入的变量的地址。
需要注意的是,如果后边有n-1个参数,那么前边一定对应n-1个%f一类的格式说明符。
●scanf()中变量前忘了加&。
记住:
scanf()中变量前要有&(但后边学到的字符数组名和指针前不用加)
6、定义标识符的时候经常出现使用非法字符的情况,例如:
标识符中不能用空格,也就是说不能有这样的定义:
intradiumofcircle;一般情况下可用下划线将三个单词连接在一起。
7、在使用变量前未定义,或未初始化。
例如:
若下边的sum未定义,则在编译时会提示相应的错误信息,而若未初始化为0,则求和的结果一定是错误的。
voidmain()
{intI,a[10],sum=0;/*只要下边要用,这个定义就必须要有,一般情况下也要有初始值*/
for(I=0;I<10;I++)sum+=a[I];
printf(“%d”,sum);
}
8、符号常量定义错误。
例如:
#definePI=3.14159,这里的=应该换成空格。
9、计算错误。
主要注意:
++,――和其它运算符一起运算时,除根据优先级进行计算时,还要考虑先后位置的特殊含义;数据类型不一致时发生的自动转换也会导致计算的误差;还要注意求模结果的符号与被除数相同;某些特殊情况下 使用懒惰求值法。
10、不能除以0,要做合法性检查;
11、类型溢出。
记住每种数据类型的取值范围,确保数据在所定义类型范围之内;
12、数学表达式的格式有误。
常见的有:
(1)数学与C语言运算表达式的混淆(例如:
=表示赋值,而==才表示我们数学中的相等关系)。
(2)、忽略了运算的优先级。
解决这个问题的最好方法就是写数学表达式时不要从左到右,而是按优先级的顺序写,写完优先级高的一个表达式后加上()再写下一级的表达式,例如:
计算梯形的面积时,要s=((a+b)*h)/2,不要1/2*a+b*h.(3)忽略了计算和赋值时的自动转换。
例如:
floathalf=1/2;这样,因为=右边是整数相除的结果为整数0,不会得到0.5存入half,进而会影响下边的计算结果。
要想不在这儿绊跟头,当计算不同类型的数据时,一定注意会不会出现引起错误的自动转换,建议最好加上强制转换。
(4)赋值号左边不是变量,例如:
若有#definePI3.14,程序中又出现PI=3.14159。
又例如:
f(n)=f(n-1)*n(这是典型的数学语言,在C语言中右边的乘积不能正确存储,而左边又是一个函数调用)。
13、使用库函数前,尤其是数学函数忘了加#include
.h>。
二、流程控制
1、丢掉语句结束标记“;”,尤其是for语句中表达式后或do-while语句后的分号,或在预处理命令后边、while()后、for()后加“;”;
2、If语句或循环语句中逻辑表达式或关系表达式书写错误。
一定要注意C语言的条件与数学表达式的区别(例如我们数学中经常写到的0≤x≤9,在C语言中应该写成x>=0&&x<=9)。
3、if-else嵌套时不配对。
最好在写每个条件时要用两个{}分别将两个分支先括起来,再添加其中的语句,以保证其配对不易错。
4、switch()语句中的格式不正确。
()中的表达式结果一定是一些明确的值,不能是区间;表达式的所有可能结果要列在case后边,case与常量之间有一空格,不要丢掉必要的break;
5、随意修改循环控制变量i的值,导致循环次数的改变,尤其是当循环有嵌套时。
在循环体中,不要将循环控制变量进行另外的改变。
6、分不清什么情况下用双重循环,什么情况下用两个控制变量写成一重循环。
当I不变,j又循环一遍的时候用双重循环。
当I,j同时变化的时候用一重循环,此时,循环控制变量有两个,但条件只写一个就可以,因为另一个总是进行相应的变化的。
7、忽略循环体与循环控制变量的关系。
其实,很多情况下,循环控制变量都在循环体中起到非常重要的作用。
应该利用上这种关系。
三、数组与指针
1、字符串的输入有错误:
主要表现在使用scanf()或gets()时加了&,或输入字符串时用循环,(这样的话,字符个数无论多长,都不会为自动加\0,将来引用的时候也就不能以字符串的形式引用。
)
2、对字符串的处理中,循环条件仍然写成I 由于字符串是不定长的,所以循环条件一般为str[I]! =’\0’或I 3、而输入所对应的变量是指针时(常见的有: 输入的变量是字符数组名或指向字符串的指针)不能加&。 4、指针定义后未赋值就引用。 如果在定义时不知道赋什么值,可以用p=NULL赋初值,以避免引起的灾难性错误。 5、分不清p和*p。 前者是指针,即地址,后者表示指针所间接引用的数据,但如果是二级指针或多级指针,取*以后得到的仍然可能是地址。 四、函数 1、函数定义的时候,函数头部加分号,而函数声明的地方忘了加分号 2、函数实参格式不对,主要表现在: 给出实参时,多给出数组类型,或者,形参是数组inta[];的时候,给出的a[]或a[I]. 3、递归时忘了设置边界条件,这样易造成死循环调用。 4、使用函数之前未声明(包括C库函数的声明)。 建议大家,将所定义的一切函数都在程序开始的预处理命令后加上函数原型的声明,这样做不仅可以避免错误,而且整个程序的结构看起来更清楚。 五、结构体共用体 1、结构体类型定义有误,主要表现在: 结构体类型里还有嵌套的时候,忘记了成员名称。 (例如: 下边的例子中,有些同学经常忽略了birthday) 2、结构体类型名和结构体变量名混淆。 例如: structSTU {…. Structdata {intyear,month,day; }birthday }; structSTUa;structSTU是类型名称,而且不分配空间,且不能直接引用。 只有定义了结构体类型structSTU的变量a以后,才为a分配相应的内存空间,引用时也要是a.? ? ? 3、结构体变量的成员引用不正确,尤其是当结构体类型中有嵌套定义的时候。 一定要一级一级的引用。 例如: 上边的例子: 如果引用其中的年的话,一定是a.birthday.year. 不能直接a.year. 4、对结构体变量进行输入输出的时候,整体输入或整体输出。 除作为函数参数外,不能对结构体变量整体操作,只能一个成员一个成员地输入、输出。 5、不理解共用体的“共占内存”。 对共用体中的成员变量,一定要靠一个标记区别它们,并分别按不同类型引用它们。 切记: 共用体变量不能做函数形参。 六、文件 1、使用之前没有打开文件,使用之后没有关闭文件。 2、相关函数的调用格式有误。 请一定注意实参的类型、顺序、个数上与函数原型(或函数声明)的一致。 VisualC++6.0中的调试工具使用入门 一、程序开发过程中出现的错误类型 我们在进行程序设计时,不可避免地会犯错误。 程序中的错误可以分为三类: 编译错误、运行时错误和逻辑错误。 编译错误(Compileerrors)又称为编译时错误(Compiling-timeerrors): 是由于错误的编码产生的。 例如关键字拼写错误、将中文标点符号当成英文符号使用、遗漏了某些必要的标点符号或者使用了一个没有定义的标识符。 编译错误一般都是语法错误,当编译器对程序进行语法检查时,都能发现这些错误,并能够指出产生错误的位置(标出行号)。 我们可以根据编译出错信息指出的行号找到对应的源代码行改正错误,重新编译源程序。 只有当所有的编译错误被改正后,才能通过编译检查,产生目标代码文件。 改正编译错误的关键是要能正确理解编译器给出的编译错误信息。 VC++环境中的编译、链接错误信息是用英文表示的。 对于英文基础薄弱的读者,可以参考本实验指导书后面的“VC++编译、链接常见错误和警告信息中英文对照”。 通常情况下,一个语法错误可能产生多条编译错误信息,这是由于株连错误造成的,建议读者在处理编译错误时,找到第一个出现错误的位置改正后重新编译。 这样能够避免被株连错误迷惑。 值得指出的是,现在大部分编译器对错误的定位不精确,如果在编译器指出的行没有发现错误,应该向前查找错误。 例如,当提示第10行发生错误时,如果在第10行没有发现错误,请从第10行开始往前查找错误并修改之。 运行时错误(Run-timeerrors)是在程序的运行阶段出现的,当运行环境检测到程序的某些操作无法执行,例如除数为零时,就会出现运行时错误。 当运行环境检测到程序的某些操作是被禁止的,也会产生运行时错误。 例如,访问数组时超越数组的边界,空指针引用(NULLpointerassignment,空指针赋值,即有指针未赋具体地址就使用了)等等。 逻辑错误(Logicerrors): 当程序没有按照程序员的意图执行时,就表明程序中存在逻辑错误。 一个应用程序可能既没有语法错误,运行时也没有执行任何无效的操作,但是有可能产生错误的结果,这种错误结果一般都是程序内部的逻辑错误造成的。 只有通过测试应用程序并分析它产生的结果,我们才能核实应用程序是否正确地执行了。 当然,如果输入了错误的或者无效的数据,执行程序后肯定也得不到正确的结果。 软件行业中有一句名言“输入的是垃圾,输出也是垃圾。 (Garbagein,garbageout.)”因此,一般的实用程序还需要对输入数据的正确性和有效性进行检验。 很显然,必须找出并改正程序中的错误,才能得到正确的执行结果。 对于语法错误,我们可以根据编译错误信息指出的位置和错误原因来改正错误。 请记住: 编译器不能发现程序中的逻辑错误和运行时错误。 我们可以通过仔细阅读源程序来发现逻辑错误,还可以借助开发环境中提供的调试工具来查找程序中的逻辑错误和运行时错误。 所谓调试(debug)就是定位程序中的错误并改正错误的过程。 为了帮助程序员找出并改正程序中的错误,微软公司在VisualC++6.0环境中集成了调试器(debugger),调试器就是调试工具(debuggingtools)。 下面我们将介绍VisualC++6.0中的调试工具及其使用方法。 二、VisualC++6.0中的调试工具简介 VisualC++6.0环境中的调试工具功能十分强大,既可以支持C++语言源代码级的调试,也可以支持汇编语言级和机器语言级的调试。 我们在此仅介绍C++语言源代码级的调试。 VisualC++6.0中的调试器允许我们在程序中设置断点(breakpoint),单步运行程序(step),运行到光标处(runtocursor),监视(watch)变量值等等。 断点是我们通过调试器在源程序中设置的一个位置。 当运行到断点时,程序中断执行,这样我们可以观察断点处各个相关变量的值,通过变量的值分析、判断到断点处时程序的执行是否符合我们的期望。 断点是最常用、最基本的技巧。 在VisualC++6.0中设置断点的最简单方法就是通过点击Build工具条上的插入断点按钮(手掌形状按钮)或者按键盘上的功能键F9。 如图13所示, 图13在源程序中设置断点 图14开始调试程序 一次可以设置多个断点,设置了断点之后,就可以通过点击Build工具条上的开始调试程序按钮或者按键盘上的功能键F5开始调试程序。 如图14所示, 图15程序运行至断点处暂停 当程序运行至断点处会暂停,我们可以在断点暂停处通过Watch窗口观察有关变量的值,如图15所示。 如果Watch窗口没有显示我们所关心的变量,可以自行添加。 另外还有一个更简单的观看变量的值方法: 当程序运行到断点时,把鼠标光标移动到源程序中的某个变量上,停留一秒钟就可以看到这个变量的值。 移去断点: 把键盘光标(插入符)移动到断点所在的行,再次按功能键F9就可以移去断点。 也可以通过点击Build工具条上的插入/移去断点按钮(手掌形状按钮)取消断点。 单步运行程序就是每一次只执行一条语句就暂停。 VisualC++6.0中的调试工具提供三种单步运行方式: StepInto,StepOver,StepOut,如图16所示。 StepInto命令的快捷键是功能键F11,StepOver命令的快捷键是功能键F10,StepOut命令的快捷键是功能键Shift+F9。 RuntoCursor(运行到光标处)命令的快捷键是功能键Ctrl+F10。 图16单步运行 每次单步运行一条语句后,都可以通过Watch(监视)窗口观察有关变量的值,或者将鼠标光标移动到源程序中的某个需要观察的变量上,停留一秒钟就可以看到这个变量的值,如图17所示。 如果我们确认当前函数中没有错误时,可以使用StepOut命令快速地执行完毕当前的函数,暂停在该函数调用的下一条语句上。 如果我们确认某一段源代码中没有错误时,可以将键盘光标(插入符)放置在这段代码的末尾处,使用RuntoCursor(运行到光标处)命令快速地执行完毕这一段代码,暂停在光标所在语句上。 例如我们可以将键盘光标移动到main函数的结尾处,然后按功能键Ctrl+F10执行RuntoCursor命令。 这样程序将运行到结束处停止。 图17单步运行后观察相关变量的值 需要停止调试程序时,可以执行StopDebugging(停止调试)命令,如图18所示。 StopDebugging命令的快捷键是功能键Shift+F5,Restart(重新开始调试程序)命令的快捷键是功能键Ctrl+Shift+F5。 Go(开始调试程序)命令的快捷键是功能键F5。 Go命令还可以使程序从当前语句运行到下一个断点处,如果后面没有断点,就运行到到程序的结尾。 除了使用快捷键和Debug(调试)菜单执行调试命令,还可以使用Debug工具条,如图19所示。 使用工具条上的QuickWatch可以添加要观察的变量或者表达式。 工具条上还有一些其他工具可以帮助我们查看CPU内部的寄存器(Registers)、内存单元(Memory)和堆栈(Stack)的情况。 VisualC++6.0中的调试工具功能强大,在这里我们只介绍最基本的操作。 当读者积累了一定的调试经验后可以继续学习调试工具的高级使用方法。 最后要强调一点,当程序员对程序进行调试时,一定要理解程序的算法,熟悉程序的结构和流程,准确估计变量和表达式的期望值。 这样才能做出正确的分析和判断。 调试的过程实质上是一个思考的过程。 图18停止调试命令等 图19调试工具条 VC++编译、链接常见错误和警告信息中英文对照 1、fatalerrorC1010: unexpectedendoffilewhilelookingforprecompiledheaderdirective。 寻找预编译头文件路径时遇到了不该遇到的文件尾。 (一般是没有#include"stdafx.h") 2、fatalerrorC1083: Cannotopenincludefile: 'R…….h': Nosuchfileordirectory 不能打开包含文件“R…….h”: 没有这样的文件或目录。 3、errorC2011: 'C……': 'class'typeredefinition 类“C……”重复定义。 4、errorC2018: unknowncharacter'0xa3' 不认识的字符'0xa3'。 (一般是汉字或中文标点符号) 5、errorC2057: expectedconstantexpression 希望是常量表达式。 (一般出现在switch语句的case分支中) 6、errorC2065: 'IDD_MYDIALOG': undeclaredidentifier “IDD_MYDIALOG”: 未声明过的标识符。 7、errorC2082: redefinitionofformalparameter'bReset' 函数参数“bReset”在函数体中重定义。 8、errorC2143: syntaxerror: missing': 'before'{' 句法错误: “{”前缺少“: ”。 9、errorC2146: syntaxerror: missing';'beforeidentifier'dc' 句法错误: 在“dc”前丢了“;”。 10、errorC2196: casevalue'69'alreadyused 值69已经用过。 (一般出现在switch语句的case分支中) 11、errorC2509: 'OnTimer': memberfunctionnotdeclaredin'CHelloView' 成员函数“OnTimer”没有在“CHelloView”中声明。 12、errorC2511: 'reset': overloadedmemberfunction'void(int)'notfoundin'B' 重载的函数“voidreset(int)”在类“B”中找不到。 13、errorC2555: 'B: : f1': overridingvirtualfunctiondiffersfrom'A: : f1'onlybyreturntypeorcallingconvention类B对类A中同名函数f1的重载仅根据返回值或调用约定上的区别。 14、errorC2660: 'SetTimer': functiondoesnottake2parameters“SetTimer”函数不传递2个参数。 15、warningC4035: 'f……': noreturnvaluef……”函数f……没有返回值。 16、warningC4553: '==': operatorhasnoeffect;didyouintend'='? 没有效果的运算符“==”;是否改为“=”? 17、warningC4700: localvariable'bReset'usedwithouthavingbeeninitialized 局部变量“bReset”没有初始化就使用。 18、errorC4716: 'CMyApp: : InitInstance': mustreturnavalue “CMyApp: : InitInstance”函数必须返回一个值。 19、LINK: fatalerrorLNK1168: cannotopenDebug/P1.exeforwriting 连接错误: 不能打开P1.exe文件,以改写内容。 (一般是P1.Exe还在运行,未关闭) 20、errorLNK2001: unresolvedexternalsymbol"……" 连接时发现没有实现的外部符号(没有定义的变量、没有定义的函数等)。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VisualC60 中的 调试 工具 使用 常见 错误