文档视界 最新最全的文档下载
当前位置:文档视界 › 程序调试与常见程序错误

程序调试与常见程序错误

程序调试与常见程序错误
程序调试与常见程序错误

程序调试与常见程序错误

目录

一、在Codeblocks中调试程序 (1)

二、存储路径设置问题 (4)

三、修改Codeblocks的设置 (4)

四、提示程序无法调试问题 (6)

五、常见错误分析 (6)

六、程序出错的三种情况 (18)

七、常用的纠错方式 (19)

一、在Codeblocks中调试程序

1.注意事项

不允许工程路径中含有空格、汉字。

2.在相应行号后面点击鼠标左键设置断点

3.打开W ATCHS窗口

4.点击调试按钮

5.可以再watchs窗口看到自动变量。黄色三角表示程序暂停的位置

6.通过单步运行按钮进行单步运行。

7.也可以在debuger标签,command栏输入调试命令进行单步运行、打印变量值等操作。

8.程序运行

二、存储路径设置问题

1. 如果不是默认安装路径,code blocks 就无法找到编译器和调试器,就会出现此类问题。

解决办法:Settings——Compiler and debugger——Toolchain executables——Auto-detect。

2. 输出信息为“某个命令执行失败或异常终止”。

解决方法:通常是相应的编译器找不到,试着将其所在路径放到path环境变量中去。

3. 输出编译错误,如某某文件找不到之类。

解决方法:在项目中设置选项中加上路径(通常可利用customer variable项)。

4. 在调试程序的时候弹出类似""XYZ - Debug": The compiler's setup (GNU GCC Compiler)

is invalid, so Code::Blocks cannot find/run the compiler.

Probably the toolchain path within the compiler options is not setup correctly?!

Goto "Settings->Compiler and debugger...->Global compiler settings->GNU GCC Compiler->Toolchain executables" and fix the compiler's setup.

Skipping...

Nothing to be done (all items are up-to-date)."这种警告。

解决方法:这个错误提示已经说得很清楚了, 找不到编译器, 到菜单Settings->Compiler and debugger...->Global compiler settings->GNU GCC Compiler->Toolchain executables下去修复编译选项前提是你已经装了gcc

如过没装, 就去下个包含mingw的codeblocks, (mingw包含gcc编译器);

三、修改Codeblocks的设置

1.

2.

3.

4.

四、提示程序无法调试问题

多次调试一个程序时出现"cannot open output film D:\c++\文件名.exe Permission denied"

解决方法:启动任务管理器,找到文件.exe关闭就可以了。

五、常见错误分析

1.忘记定义变量。

例如:

main()

{x=3;

y=6;

printf("%d\n",x+y);

C要求对程序中用到的每一个变量都必须定义其类型,上面程序中没有对x、y进行定义。应在函数体的开头加int x,y;这是学过BASIC和FORTRAN语言的读者写C程序时常见的一个错误。在BASIC语言中,可以不必先定义变量类型就可直接使用。在FORTRAN 中,未经定义类型的变量按隐含的I-N规则决定其类型,而C语言则要求对用到的每一个

变量都要在本函数中定义(除非已定义为外部变量)。

2.输入输出的数据的类型与所用格式说明符不一样。

例如:

若a已定义为整型,b已定义为实型。

a=3;b=4.5;

printf("%f%d\n",a,b);

编译时不给出出错信息,但运行结果将与原意不符,输出为

0.00000016402

它们并不是按照赋值的规则进行转换(如把4.5转换成4),而是将数据在存储单元中的形式按格式符的要求组织输出(如b占4个字节,只把最后两个字节中的数据按%d,作为整数输出)。

3.未注意int型数据的数值范围。

例如:

一般微型计算机上使用的C编译系统,对一个整型数据分配两个字节。因此一个整数的范围为

-215~215-1,即-32768~32767。常见这样的程序段:

int num;

num=89101;

printf("%d",num);

得到的却是23565,原因是89101已超过32767。两个字节容纳不下89101,则将高位截去。即将超过低16位的数截去。即将89101减去216(即16位二进制所形成的模)。89101-65536=23565。

有时还会出现负数。例如

num=196607;

输出得-1。因为196607的二进制形式为

00 00 00 00 00 00 00 1011 11 11 11 11 11 11 11

去掉高位10,低16位的值是-1(-1的补码是:1111111111111111)。

对于超过整个范围的数,要用long型,即改为

long int num;

num=89101;

printf("%ld",num);

请注意,如果只定义num为long型,而在输出时仍用“%d”说明符,仍会出现以上错误。

4.在输入语句scanf中忘记使用变量的地址符。

例如:

scanf("%d%d",a,b);

这是许多初学者刚学习C语言时一个常见的疏忽,或者说是习惯性的错误,因为在其他语言中在输入时只需写出变量名即可,而C语言要求指明“向哪个地址标识的单元送值”。

应写成scanf("%d%d",&a,&b);

5.输入时数据的组织与要求不符。

例如:

用scanf函数输入数据,应注意如何组织输入

数据。假如有以下scanf函数:

scanf("%d%d",&a,&b);

有人按下面的方法输入数据:

3,4

这是错的。数据间应该用空格来分隔。读者可以用

printf("%d%d",a,b);

来验证一下。应该用以下方法输入:

34

如果scanf函数为

scanf("%d,%d",&a,&b);

对scanf函数中格式字符串中除了格式说明符外,

对其他字符必须按原样输入。因此,应按以下方法输入:

3,4

此时如果用“34”反而错了。还应注意,不能企图用

scanf("input a & b:%d,%d",&a,&b);

想在屏幕上显示一行信息:

input a & b:

然后在其后输入a和b的值,这是不行的。这是由于有的读者以为scanf具有BASIC语言中的INPUT语句的功能(先输出一个字符串,再输入变量的值)。如果想在屏幕上得到所需的提示信息,可以另加一个printf函数语句:printf("input a & b:");

scanf("%d,%d",&a,&b);

6.误把“=”作为“等于”运算符。

例如:

在许多高级语言中,用“=”符号作为关系运算符“等于”。例如,在BASIC或PASCAL 程序中都可以写

if(a=b)then…

但在C语言中,“=”是赋值运算符,“==”才是关系运算符“等于”。如果写成

if(a=b)printf("a equal to b");

C编译系统将(a=b)作为赋值表达式处理,将b的值赋给a,然后判断a的值是否零,若为非零,则作为“真”;若为零作为假。如果a的值为3,b的值为4,

a≠b,按原意不应输出“ae q u a lt ob”。而现在先将b的值赋给a,a也为4,赋值表达式的值为4。if语句中的表达式值为真(非零),因此输出“ae q u a lt o b”。

这种错误在编译时是检查不出来的,但运行结果往往是错的。而且由于习惯的影响,程序设计者自己往往也不易发觉。

7.语句后面漏分号。

例如:

C语言规定语句末尾必须有分号。分号是C语句不可缺少的一部分。这也是和其他语言不同的。有的初学者往往忘记写这一分号。如:

a=3

b=4

编译时,编译程序在“a=3”后面未发现分号,就把下一行“b=4”也作为上一行的语句的一部分,这就出现语法错误。有时编译时指出某行有错,但在该行上并未发现错误,应该检查上一行是否漏了分号。

如果用复合语句,有的学过PASCAL语言的读者往往漏写最后一个语句的分号,如:{t=a;

a=b;

b=t

在PASCAL中分号是两个语句间的分隔符而不是语句的一部分,而在C中,没有分号的就不是语句。

8.在不该加分号的地方加了分号。

例如:

if(a>b);

printf("a is larger than b\n");

本意为当a>b时输出“a is larger than b”的信息。

但由于在if(a>b)后加了分号,因此if语句到此结束。即当(a>b)为真时,执行一个空语句。本来想a≤b时不输出上述信息,但现在printf函数语句并不从属于if语句,而是与if语句平行的语句。不论

a>b还是a≤b,都输出“a is larger than b”。

又如:

for(i=0;i<10;i++);

{scanf("%d",&x);

printf("%d\n",x*x);

本意为先后输入10个数,每输入一个数后输出它的平方值。由于在for()后加了一个分号,使循环体变成了空语句。只能输入一个整数并输出它的平方值。

总之,在if、for、while语句中,不要画蛇添足多加分号。

9.对应该有花括号的复合语句,忘记加花括号。

例如:

sum=0;

i=1;

while(i<=100)

sum=sum+i;

i++;

本意是实现1+2+…+100,即∑i。但上面的语句只是重复了sum+1的操作,而且循环永不终止。因为i的值始终没有改变。错误在于没有写成复合语句形式。因此while语句的范围到其后第一个分号为止。语句“i++;”不属于循环体范围之内。应改

while(i<=100)

{sum=sum+i;

i++;

10.括号不配对。

例如:

当一个语句中使用多层括弧时常出现这类错误,纯属粗心所致。如:while((c=getchar()!='#')

putchar(c);

少了一个右括弧。

11.在用标识符时,忘记了大写字母和小写字母的区别。

例如:

main()

{int a,b,c;

a=2;b=3;

C=A+B;

printf("%d+%d=%",A,B,C);

编译时出错。编译程序把a和A认作是两个不同的变量名处理,同样b和B,c和C都分别代表两个不同的变量。

12.引用数组元素时误用了圆括弧。

例如:

main()

{int i,a(10);

for(i=0;i<10;i++)

scanf("%d",&a(i));

C语言中对数组的定义或引用数组元素时必须用方括弧[ ]。

13.在定义数组时,将定义的“元素个数”误认为是“可使用的最

大下标值”。

例如:

main()

{int a[10]={1,2,3,4,5,6,7,8,9,10};

int i;

for(i=1;i<=10;i++)

printf("%d",a[i]);

想输出a[1]到a[10],是一些初学者常犯的错误。C语言规定定义时用a[10],表示a数组有10个元素,而不是可以用的最大下标值为10。数组只包括a[0]到a[9]10个元素,因此用a[10]就超出a数组的范围了。

14.对二维或多维数组的定义和引用的方法不对。

例如:

main()

{int a[5,4];

printf("%d",a[1+2,2+2]);

对二维数组和多维数组在定义和引用时必须将每一维的数据分别用方括弧括起来。上面a[5,4]应改为a[5][4],a[1+2,2+2]应改为a[1+2][2+2]。根据C的语法规则,在一个方括弧中的是一个维的下标表达式,a[1+2,2+2]中方括弧中的“1+2,2+2”是一个逗号表达式,它的值是第二个数值表达式的值,即2+2的值为4。所以a[1+2,2+2]相当于a[4]。而a[4]是a数组的第4行的首地址。因此执行printf函数输出的结果并不是a[3][4]的值,而是a数组第4行的首地址。

15.误认为数组名代表数组中全部元素。

例如:

main()

{int a[4]={1,3,5,7};

printf("%d%d%d%d\n",a);

企图用数组名代表全部元素。在C语言中,数组名代表数组首地址,不能通过数组名输出4个整数。

16.混淆字符数组与字符指针的区别。

例如:

main()

{char str[4];

str="Computer and c";

printf("%s\n",str);

编译出错。str是数组名,代表数组首地址。在编译时对str数组分配了一段内存单元,因此在程序运行期间str是一个常量,不能再被赋值。因此,

str=“Computer and c”是错误的。如果把“char str[4];”改成“char str;”,则程序正确。此时str是指向字符数据的指针变量,str=“Computer and c”是合法的,它将字符串的首地址赋给指针变量str,然后在printf函数语句中输出字符串“Computer and c”。

因此应当弄清楚字符数组与字符指针变量用法的区别。

17.在引用指针变量之前没有对它赋值。

例如:

main()

{char*p;

scanf("%s",p);

没有给指针变量p赋值就引用它,编译时给出警告信息。应当改为

Char*p,c[20];

p=c;

scanf("%s",p);

即先根据需要定义一个大小合适的字符数组c,然后将c数组的首地址赋给指针变量p,此时p有确定的值,指向数组c。再执行scanf函数就没有问题了,把从键盘输入的字符串存放到字符数组c中。

18.Switch语句的各分支中漏写break语句。

例如:

switch(score)

{case 5:printf("Very good!");

case 4:printf("Good!");

case 3:printf("Pass!");

case 2:printf("Fail!");

defult:printf("data error!");

上述switch语句的作用是希望根据score(成绩)打印出评语。但当score的值为5时,输出为

Very Good!Good!Pass!Fail!data error!

原因是漏写了break语句。case只起标号的作用,而不起判断作用,因此在执行完第一个printf函数语句后接着执行第2、3、4、5个printf函数语句。应改为

switch(score)

{case 5:printf("Verygood!");break;

case 4:printf("Good!");break;

case 3:printf("Pass!");break;

case 2:print("Fail!");break;

defult:print("data error!");

19.混淆字符和字符串的表现形式。

例如:

char sex;

sex="M";

sex是字符变量,只能存放一个字符。而字符常量的形式是用单引号括起来的,应改为sex='M';

“M”是用双引号括起来的字符串,它包括两个字符:‘M’和‘\0’,无法存放到字符变量sex中。

20.使用自加(++)和自减(- -)运算符时出的错误。

例如:

main()

{int p,a[5]={1,3,5,7,9};

p=a;

printf("%d",*p++);

不少人认为“*p++”的作用是先使p加1,即指向第1个元素a[1]处,然后输出第一个元素a[1]的值3。其实应该是先执行p++,而p++的作用是先用p的原值,用完后使p加1。p的原值指向数组a的第0个元素a[0],

因此*p就是第0个元素a[0]的值1。结论是先输出a[0]的值,然后再使p加1。如果是*(++p),则先使p指向a[1],然后输出a[1]的值。

21.有人习惯用传统的方式对函数形参进行声明,但却把对函数的

形参和函数中的局部变量混在一起定义。

例如:

max(x,y)

int x,y,z;

{z=x>y?x,y;

return(z);

应改为

max(x,y)

int x,y;

{int z;

z=x>y?x:y;

return(z);

22.所调用的函数在调用语句之后才定义,而又在调用前未加说

明。

例如:

main()

{float x,y,z;

x=3.5;y=-7.6;

z=max(x,y);

printf("%f\n",z);

float max(float x,float y)

{return(z=x>y?x:y);

这个程序乍看起来没有什么问题,但在编译时有出错信息。原因是max函数是实型的,而且在main函数之后才定义,也就是max函数的定义位置在main函数中的调用max函数之后。改错的方法可以用以下二者之一:

①在main函数中增加一个对max函数的声明,即函数的原型:

main()

{float max(float,float);/*声明将要用到的max函数为实型*/

float x,y,z;

x=3.5;y=-7.6;

z=max(x,y);

printf("%f\n",z);

②将max函数的定义位置调到main函数之前。即:float max(float x,float y)

{return(z=x>y?x:y);}

main()

{float x,y,z;

x=3.5;y=-7.6;

z=max(x,y);

printf("%f\n",z);

这样,编译时不会出错,程序运行结果是正确的。

23.误认为形参值的变化会影响实参的值。

例如:

main()

{inta,b;

a=3;b=4;

swap(a,b);

printf("%d,%d\n",a,b);

swap(int x,int y)

{int t;

t=x;x=y;y=t;

p1=&a;p2=&b;

swap(p1,p2);

printf("%d,%d\n",a,b);/*a和b的值已对换*/

swap(int *pt1,int *pt2)

{int t;

t=*pt1;*pt1=*pt2;*pt2=t;

24. 函数的实参和形参类型不一致。

例如:

main()

{int a=3,b=4;

c=fun(a,b);

fun(float x,float y)

实参a、b为整型,形参x、y为实型。a和b的值传递给x和y时,x和y的值并非3和4。C要求实参与形参的类型一致。如果在main函数中对fun作原型声明:fun (float, float);

程序可以正常运行,此时,按不同类型间的赋值的规则处理,在虚实结合后x=3.0, y=4.0。也可以将fun函数的位置调到main函数之前,也可获正确结果。

25.不同类型的指针混用。

例如:

main()

{int i=3,*p1;

float a=1.5,*p2;

p1=&i;p2=&a;

p2=p1;

printf("%d,%d\n",*p1,*p2);

企图使p2也指向i,但p2是指向实型变量的指针,不能指向整型变量。指向不同类型的指针间的赋值必须进行强制类型转换。如:

p2=(float*)p1;

作用是先将p1的值转换成指向实型的指针,然后再赋给p2。

这种情况在C程序中是常见的。例如,用malloc函数开辟内存单元,函数返回的是指向被分配内存空间的void *类型的指针。而人们希望开辟的是存放一个结构体变量值的存储单元,要求得到指向该结构体变量的指针,可以进行如下的类型转换。

struct student

{int num;

char name[20];

float score;

};

struct student student1,*p;

p=(struct student *)malloc(LEN);

p是指向struct student结构体类型数据的指针,将malloc函数返回的void *类型指针转换成指向struct student类型变量的指针。

26.没有注意函数参数的求值顺序。

例如:

i=3;

printf("%d,%d,%d\n",i,++i,++i);许多人认为输出必然是

3,4,5

实际不尽然。在Turbo C和其他一些C系统中输出是

5,5,4

因为这些系统是采取自右至左的顺序求函数参数的值。先求出最右面一个参数(++i)的值为4,再求出第2个参数(++i)的值为5,最后求出最左面的参数(i)的值5。

C标准没有具体规定函数参数求值的顺序是自左而右还是自右而左。但每个C编译程序都有自己的顺序,在有些情况下,从左到右求解和从右到左求解的结果是相同的。例如fun1(a+b,b+c,c+a);

fun1是一个函数名。3个实参表达式a+b、b+c、c+a。在一般情况下,自左至右地求这3个表达式的值和自右至左地求它们的值是一样的,但在前面举的例子是不相同的。因此,建议最好不用会引起二义性的用法。如果在上例中,希望输出“3,4,5”时,可以改用i=3;j=i+1;k=j+1;

printf("%d,%d,%d\n",i,j,k);

27.混淆数组名与指针变量的区别。

例如:

main()

{int i,a[5];

for(i=0;i<5;i++)

scanf("%d",a++);

企图通过a的改变使指针下移,每次指向欲输入数据的数组元素。它的错误在于不了解数组名代表数组首地址,它的值是不能改变的,用a++是错误的,应当用指针变量来指向各数组元素。即:

int i,a[5],*p;

p=a;

for(i=0;i<5;i++)

scanf("%d",p++);

或int a[5],*p;

for(p=a;p<a+5;p++)

scanf("%d",p);

28.混淆结构体类型与结构体变量的区别,对一个结构体类型赋

值。

例如:

struct worker

{long int num;

char name[20];

char sex;

int age;

};

worker.num=187045;

strcpy(worker.name,"ZhangFun");

worker.sex='M';

worker.age=18;

这是错误的,只能对变量赋值而不能对类型赋值。上面只定义了struct worker类型而未定义变量。应改为

struct worker

{long int num;

char name[20];

char sex;

int age;

};

struct worker worker-1;

worker-1.num=187045;

strcpy(worker-1.name,"Zhang Fun");

worker-1.sex='M';

worker-1.age=18;

今定义了结构体变量worker-1,并对其中的各成员赋值。

29.使用文件时忘记打开,或打开方式与使用情况不匹配。

例如:

对文件的读写,用只读方式打开,却企图向

该文件输出数据,例如:

if((fp=fopen("test","r"))==NULL)

{printf("cannot open this file\n");

exit(0);

ch=fgetc(fp);

while(ch!='#')

{ch=ch+4;

fputc(ch,fp);

ch=fget(fp);

对以“r”方式(只读方式)打开的文件,进行既读又写的操作,显然是不行的。

此外,有的程序常忘记关闭文件,虽然系统会自动关闭所用文件,但可能会丢失数据。因此必须在用完文件后关闭它。

六、程序出错的三种情况

以上只是列举了一些初学者常出现的错误,这些错误大多是对于C语法不熟悉之故。对C语言使用多了,比较熟练了,犯这些错误自然就会减少了。在深入使用C语言后,还会出现其他一些更深入、更隐蔽的错误。

1.语法错误

指违背了C语法的规定,对这类错误,编译程序一般能给出“出错信息”,并且告诉你在哪一行出错。只要细心,是可以很快发现并排除的。

2.逻辑错误

程序并无违背语法规则,但程序执行结果与原意不符。这是由于程序设计人员设计的算法有错或编写程序有错,通知给系统的指令与解题的原意不相同,即出现了逻辑上的混乱。例如:前面第9条错误:

sum=0;i=1;

while(i<=100)

sum=sum+i;

i++;

语法并无错误。但while语句通知给系统的信息是当i≤100时,执行“sum=sum+i;”。

C系统无法辨别程序中这个语句是否符合作者的原意,而只能忠实地执行这一指令。这种错误比语法错误更难检查。要求程序员有较丰富的经验。

3.运行错误。

程序既无语法错误,也无逻辑错误,但在运行时出现错误甚至停止运行。例如:

int a ,b ,c;

scanf("%d %d",&a,&b);

c=b/a;

printf("c=%d\n",c);

输入a和b的值,输出b/a的值,程序没有错。但是如果输入a的值为0,就会出现错误。因此程序应能适应不同的数据,或者说能经受各种数据的“考验”,具有“健壮性”。

写完一个程序只能说完成任务的一半(甚至不到一半)。调试程序往往比写程序更难,更需要精力、时间和经验。常常有这样的情况:程序花一天就写完了,而调试程序二三天也未能完。有时一个小小的程序会出错五六处,而发现和排除一个错误,有时竟需要半天,甚至更多。希望读者通过实践掌握调试程序的方法和技术。

七、常用的调试技术

1.单步调试

利用编译环境自带的调试工具,一步一步的跟踪变量的值。当变量的值发生错误的时候,程序的bug就在单步运行到的地方。这种方法具有局限性,比如bug发生在一个程序基本要结束的地方,但是还是需要从程序开始的地方一步一步的调试到这里,非常的浪费时间,但是对于小程序的话或者错误很难找的情况下还是可以使用的。

采用这种办法常常需要掩蔽(注释掉)部分确认没有出错的程序以提高效率。

2.输出中间结果

这种方法在竞赛中非常常用,通过在你认为会出现错误的地方,输出中间变量的值,来确定是否出错,如果变量的值和你计算的结果不符,就改正该错误的地方。正确的话,就继续在其它你认为会出错的地方,继续输出中间变量,直到找到所有bug。特别注意调试完成后应将输出中间变量的语句删除或者注释掉。

3.静态查错

即用肉眼观察代码,找到bug,这一常被人们忽略的原始方法是上面两种方法的有效补充,有时非常奏效并且节省时间。

(编写:网络12-3于立东,校核:计算机11-1陈禹,2013-9-25)

C语言调试常见错误及修改方法(附习题)

1.调试 C 程序时常见的错误类型分析 一般情况下,错误主要分为两大类:一、语法错误。对于这种错误,用编译器很容易解决。所以,改错题的第一步是先编译,解决这类语法错误。下面总结了二级C 语言上机改错题中常见的语法错误: (1) 丢失分号,或分号误写成逗号。 (2) 关键字拼写错误,如本来小写变成大写。 (3) 语句格式错误,例如for 语句中多写或者少写分号。 (4) 表达式声明错误,例如:少了() (5) 函数类型说明错误。与main ()函数中不一致。 (6) 函数形参类型声明错误。例如:少* 等。 (7) 运算符书写错误,例如:/ 写成了。二、逻辑错误,或者叫语义错误,这和实现程序功能紧密相关,一般不能用编译器发现。对于逻辑错误可以按这样的步骤进行查找。 (1) 先读试题,看清题目的功能要求。 (2) 通读程序,看懂程序中算法的实现方法。 (3) 细看程序,发现常见错误点。 2.改错题的改错方式总结,当然这些总结只能对大部分改错行有效 1、若错误行是函数首部,可分为以下几种情况: A、该行最后若有分号则删除,中间若有分号则改成逗号 B、形参类型不一致的问题,特别是指针类型,若后面用到某形参时有指针运算则该形参必为指针类型;若形参是二维数组或指向m 个元素的指针变量,则第二维的长度必须与main 中对应数组的第二维长度相同 C、函数类型不一致的问题,若函数中没有return语句则函数类型为void,若有return语句则函数的类型必须与return 后变量的类型一致。 2、若错误行是if 或while 语句,则首先看有没有用小括号将整个表达式括起,若没有则加上小括号。 3、若错误行中有if、while 、for 则要特别注意条件表达式的错误问题: A、指针变量的应用,若表达式中有指针变量且没有指针运算符,则加上指针运算符 B、若条件表达式中只有一个等于号,则改成两个等于号,若为其它比较运算符则一般是进行逆转或加一个等于号 C、f or 中要用分号分隔表达式,而不是用逗号 4、语法错误 A、语句缺少分号,若错误行中有语句没有用分号结束,则加上分号。 B、大小写不对,若错误行中有大写字母则一般都改成小写字母。 5、指针变量的运用,若错误行中有指针变量,并且该变量名前没有指针运算符则一般都是加上指针运算符 6、若错误行为return 语句,则首先看是否是缺少分号若是则加上分号即可;否则就是return 后的变量或表达式错误(此时可通过看题意,来分析该返回哪一变量或表达式)

软件调试技巧

软件调试技巧 一、软件调试方法 软件调试有很多种方法。常用的有4种,即强行排错法、回溯排错法、归纳排错法和演绎排错法。 1.强行排错法 这种方法需要动脑筋动的地方比较少,因此叫强行排错。通常有以下3种表现形式: ●打印内存变量的值。在执行程序时,通过打印内存变量的数值,将该数值同预期的数值进行比较,判 断程序是否执行出错。对于小程序,这种方法很有效。但程序较大时,由于数据量大,逻辑关系复杂,效果较差。 ●在程序关键分支处设置断点,如弹出提示框。这种方法对于弄清多分支程序的流向很有帮助,可以很 快锁定程序出错发生的大概位置范围。 ●使用编程软件的调试工具。通常编程软件的IDE集成开发环境都有调试功能,使用最多的就是单步调 试功能。它可以一步一步地跟踪程序的执行流程,以便发现错误所在。 2.回溯排错法 这是在小程序中常用的一种有效的调试方法。一旦发现了错误,可以先分析错误现象,确定最先发现该错误的位置。然后,人工沿程序的控制流程,追踪源程序代码,直到找到错误根源或确定错误产生的范围。 3.归纳排错法 归纳法是一种从特殊推断一般的系统化思考方法。归纳法调试的基本思想是,从一些线索(错误的现象)着手,通过分析它们之间的关系来找出错误,为此可能需要列出一系列相关的输入,然后看哪些输入数据的运行结果是正确的,哪些输入数据的运行结果有错误,然后加以分析、归纳,最终得出错误原因。 4.演绎排错法 演绎法是一种从一般原理或前提出发,经过排除和精化的过程来推导出结论的思考方法。调试时,首先根据错误现象,设想及枚举出所有可能出错的原因作为假设。然后再使用相关数据进行测试,从中逐个排除不可能正确的假设。最后,再用测试数据验证余下的假设是否是出错的原因。 二、调试的原则 调试能否成功一方面在于方法,另一方面很大程度上取决于个人的经验。但在调试时,通常应该遵循以下一些原则。 1.确定错误的性质和位置的原则 用头脑去分析思考与错误征兆有关的信息,避开死胡同。调试工具只是一种辅助手段。利用调试工具可以帮助思考,但不能代替思考。通常避免使用试探法,最多只能将它当作最后的手段,毕竟小概率事件有时也会发生。 2.修改错误的原则 在出现错误的地方,很可能还有别的错误。修改错误的一个常见失误是只修改了这个错误的征兆或这个错误的表现,而没有修改错误本身。当新修正一个错误的同时又引入新的错误。 三、有效减少调试时间 1.绘制程序流程图 一些程序员认为,绘制程序流程图是件繁琐的事,而且浪费时间。其实不然,当读者对着偌大的程序一筹莫展时,面对纷纭复杂的关系理不出头绪时,使用程序流程图绝对可以事半功倍。 因此建议在编制程序前先绘制流程图,这样编程的思路有条理,调试时同样会有条不紊。若编制程序之前没有绘制流程图,当排错没有进展时,可以马上编写流程图。你会发现,程序中某些分支或细节被忽略了,这些细节可能就是程序出错的地方。 2.不要过多地依赖单步调试 有些程序对时间很敏感。数据只在那么一瞬间有效,可谓稍纵即逝。所以等到单步执行到那里时,

程序调试与常见程序错误

程序调试与常见程序错误 目录 一、在Codeblocks中调试程序 (1) 二、存储路径设置问题 (4) 三、修改Codeblocks的设置 (4) 四、提示程序无法调试问题 (6) 五、常见错误分析 (6) 六、程序出错的三种情况 (18) 七、常用的纠错方式 (19) 一、在Codeblocks中调试程序 1.注意事项 不允许工程路径中含有空格、汉字。 2.在相应行号后面点击鼠标左键设置断点 3.打开W ATCHS窗口

4.点击调试按钮 5.可以再watchs窗口看到自动变量。黄色三角表示程序暂停的位置

6.通过单步运行按钮进行单步运行。 7.也可以在debuger标签,command栏输入调试命令进行单步运行、打印变量值等操作。 8.程序运行

二、存储路径设置问题 1. 如果不是默认安装路径,code blocks 就无法找到编译器和调试器,就会出现此类问题。 解决办法:Settings——Compiler and debugger——Toolchain executables——Auto-detect。 2. 输出信息为“某个命令执行失败或异常终止”。 解决方法:通常是相应的编译器找不到,试着将其所在路径放到path环境变量中去。 3. 输出编译错误,如某某文件找不到之类。 解决方法:在项目中设置选项中加上路径(通常可利用customer variable项)。 4. 在调试程序的时候弹出类似""XYZ - Debug": The compiler's setup (GNU GCC Compiler) is invalid, so Code::Blocks cannot find/run the compiler. Probably the toolchain path within the compiler options is not setup correctly?! Goto "Settings->Compiler and debugger...->Global compiler settings->GNU GCC Compiler->Toolchain executables" and fix the compiler's setup. Skipping... Nothing to be done (all items are up-to-date)."这种警告。 解决方法:这个错误提示已经说得很清楚了, 找不到编译器, 到菜单Settings->Compiler and debugger...->Global compiler settings->GNU GCC Compiler->Toolchain executables下去修复编译选项前提是你已经装了gcc 如过没装, 就去下个包含mingw的codeblocks, (mingw包含gcc编译器); 三、修改Codeblocks的设置 1.

3-2节 程序调试的方法

3-2节程序调试的方法 编程是一件需要认真和细心的工作。通过让学生从李明同学学习程序设计时所遇到的困难和他情感上所表现出来的“窘态”故事开始,道出程序调试不但需要技巧、更需要有耐心和毅力的道理,从而激发学生学习程序调试的兴趣和热情,拉开了本节的充幕。 接着,布置任务,让学生输入课本P83四段有错误的程序,要求学生自己探究,并改正程序。 最后分析程序运行的情况,总结出程序运行出错的四种类型: 一、拼写错误 1)在工程窗口中,看到红色文字显示的程序是有拼写错误的。 2)同时还要检查其它的拼写错误 Pring改为print Integr改为integer 2、编译时出现的错误 S应该改为a 3、运行时出现的错误 运行时的错误是指编译通过后,在执行程序时出现的错误,如用0作除数等。

例如:a=0的时候,将会出现0作除数的情形 4、逻辑错误 程序运行后,得出的结果不是正确的。这说明程序存在逻辑错误。逻辑错误产生 的原因很多,运算符使用不正确、语句次序不对、循环的设置不对等都可以产生 逻辑错误。 如这里的程序的出口应该是tree>=100 任务: P85 马上行动:

你和同学们能解决以上的问题吗?以合作、交流的方式大胆尝试一下,你会有意外的收获! 一、本节小结: 本节主要通过任务驱动、探究的形式,介绍了程序的错误类型,分析了产生错误的原因,程序的调试与排错的方法,让学生“从做中学”,进一步体验了程序调试的方法和技巧,培养了 学生调试程序的耐心和毅力,提高了学生程序设计的素养。 五、课外练习 编写一个程序,将从键盘输入的一个自然数进行因数分解,输出结果并上机验证。

DSP调试及烧写和加载常见错误及分析

Error: Read status value 0x0001 from symbol PRG_status Flash algorithm failed during clear operation 开始可以正常烧写的,但是上机调试了一下就不能写了. 在烧写lf2407内部flash时出现如下错误,不知是什么原因造成的? Error:Read status value 0x0001 from symbol PRG_status Flash algorithm failed during clear operation. 换了一个芯片后正常 之前有一次在试CCS功能时,一不小心点了一次加密,还没有执行完,就马上点了解密,大概这样烧坏了吧! 太脆弱了,再也不敢试加密了 CMD文件要避开FLASH的40H--44H区间, 我也出现过这样的问题,烧写2407A的片内flash时会出现下面的错误提示:Error: Read status value 0x0001 form symbol PRG_status Flash algorithm failed during clear operation 后来换了一块2407就能烧写了。 是不是2407的flash坏了?有没有办法检测或者修复flash? 昨天在网上查了一下,很多人都遇到了这种问题,可能是dsp内部flash烧坏了吧! 今天重新换了一块芯片,可以烧录进去了,但是上拿到样机上调试一下,再烧录就出现了同样的问题,估计又是flash坏了,到底是什么原因引起的?是不是电源引起的呢? 我也出现过能仿真,但不能烧写的情况!解决方法: 解决方法:降低时钟频率。点击FLASH插件上的“View Config File”,打开VAR.h文件。将该文件中的“PLL_PATIO_CONST .Set 0000h”改成 “PLL_PATIO_CONST .Set 0200h”存盘后,执行目录下的Buildall.bat批处理文件。再重新启动CCS及FLASH插件。 请教高手:在烧写程序的时候出现如下错误:Error: Read status value 0x0001 from s ymbol PRG_status Flash algorithm failed during clear operation

应用程序错误该如何调试

explorer exe 应用程序错误该如何调试explorer.exe应用程序错误该如何调试2010-12-24 16:10 原因很多,解释方法不一。下面解释一下这方面的问题,仅供参考: 第一个简单明了的解释: 一是系统程序中病毒而遭到破坏,二是硬件即内存有问题。 解决方法一是自己或请维修人员重装系统程序。 二是用升级后的杀毒软件杀毒修补漏洞后,重启机器。 至于再多的问题就得请电脑维修高手来上门给你维修了。下面的内容是详细解释。第二个解释: 查到下面一些,希望能对你有所帮助。 关于内存不能read,written的解决方案 这种情况偶尔出现,没什么关系,不用管他。点击'取消'就可以了。 经常出现就危险了,弄不好就得重装系统了。 运行某些程序的时候,有时会出现内存错误的提示,然后该程序就关闭。 "0x?"指令引用的"0x?"内存。该内存不能为"read"。 "0x?"指令引用的"0x?"内存,该内存不能为"written"。 一般出现这个现象有方面的,一是硬件,即内存方面有问题,二是软件 故障分析 硬件方面: 一般来说,内存出现问题的可能性并不大,主要方面是:内存条坏了、内存质量有问题,还有就是2个不同牌子不同容量的内存混插,也比较容易出现不兼容的情况,同时还要注意散热问题,特别是超频后。你可以使用MemTest这个软件来检测一下内存,它可以彻底的检测出内存的稳定度。

假如是双内存,而且是不同品牌的内存条混插或者买了二手内存时,出现这个问题,这时,就要检查是不是内存出问题了或者和其它硬件不兼容。 软件方面: 先简单说说原理:内存有个存放数据的地方叫缓冲区,当程序把数据放在其一位置时,因为没有足够空间,就会发生溢出现象。举个例子:一个桶子只能将一斤的水,当放入两斤的水进入时,就会溢出来。而系统则是在屏幕上表现出来。这个问题,经常出现在windows2000和XP系统上,Windows 2000/XP对硬件的要求是很苛刻的,一旦遇到资源死锁、溢出或者类似Windows 98里的非法操作,系统为保持稳定,就会出现上述情况。另外也可能是硬件设备之间的兼容性不好造成的。 几个例子 例一:打开IE浏览器或者没过几分钟就会出现"0x70dcf39f"指令引用的"0x 00000000"内存。该内存不能为"read"。要终止程序,请单击"确定"的信息框,单击"确定"后,又出现"发生内部错误,您正在使用的其中一个窗口即将关闭"的信息框,关闭该提示信息后,IE浏览器也被关闭。 解决方法:修复或升级IE浏览器,同时打上补丁。看过其中一个修复方法是,Win2000自升级,也就是Win2000升级到Win2000,其实这种方法也就是把系统还原到系统初始的状态下。比如你的IE升级到了6.0,自升级后,会被IE5.0代替/运用腾讯浏览器/ 例二:在windows xp下双击光盘里面的"AutoRun.exe"文件,显示"0x77f745cc"指令引用的"0x 00000078"内存。该内存不能为"written",要终止程序,请单击"确定",而在Windows 98里运行却正常。 解决方法:这可能是系统的兼容性问题,winXP的系统,右键"AutoRun.exe"文件,属性,兼容性,把"用兼容模式运行这个程序"项选择上,并选择"Windows 98/Me"。win2000如果打了SP的补丁后,只要开始,运行,输入:regsvr32 c:\winnt\apppatch\slayerui.dll。右键,属性,也会出现兼容性的选项。 例三:RealOne Gold关闭时出现错误,以前一直使用正常,最近却在每次关闭时出现"0xffffffff"指令引用的"0xffffffff"内存。该内存不能为"read"的提示。 解决方法:当使用的输入法为微软拼音输入法2003,并且隐藏语言栏时(不隐藏时没问题)关闭RealOne就会出现这个问题,因此在关闭RealOne之前可以显示语言栏或者将任意其他输入法作为当前输入法来解决这个问题。 例四:我的豪杰超级解霸自从上网后就不能播放了,每次都提示"Ox 060692f6"(每次变化)指令引用的"Oxff 000011"内存不能为"read",终止程序请按确定。

ccs33中建立-编译-调试工程及常见错误讲解.

Part1:ccs3.3中新建一个DM6437的示例工程 1、连接好板子,将板子上仿真器的usb口插到电脑上,启动ccs后,ccs会去获取板子信息并在打开的文件目录中自动生成一个文件,如图所示:笔者使用的是6437的板子 2、用file-new选择建立一个dsp/bios文件 在打开的对话框中选择你使用的板子的型号,如下图: 3、这个时候ccs为我们建立了一个bios文件,以图表显示,里面按照所选板子的类型添加相应的硬件和其他模块。保存这个文件到工程目录下先,文件类型为tcf。 4、保存这个文件的同时,ccs按照bios中的配置在当前目录下自动生成了一个cmd文件。此时将tcf文件和这个cmd文件同时添加到工程中,使用 5、然后需要修改一个编译选项,点击下图所示选项进去:

6、打开后在编译选项对话框总会看到一个命令行,其中最后一句是-mv6400,因为用的是6467的板子,所以这个选项要修改成-mv64+;否则编译会报错:编译选项不正确;但并非所有类型的板子都要改,这个只针对型号为64+的板子。 7、file-new-source file建立一个c源文件,保存并加入到工程中。 以下是示例程序: #include #include #include Int main(Int argc, String argv[])//main函数的类型必须这样写 { unsigned int i; unsigned int sum=0; for(i = 0; i<=100; i++ ) {

sum += i; } printf("the sum = %d .\n",sum); printf("the program run over!\n"); printf("the program run over!\n");} 注意:1)如果想要printf正确输出信息,需要添加对应平台的rts64plus.lib文件。这里是64+平台所以是在C:\CCStudio_v3.3\C6000\cgtools\lib目录下的rts64plus.lib文件,否则ccs 会提示如下警告和错误: >> warning: entry point symbol _c_int00 undefined undefined first referenced symbol in file --------- ---------------- _printf E:\\WorkContent\\projectExample\\Test\\Debug\\test.obj >> error: symbol referencing errors - './Debug/Test.out' not built 2)如果想要printf正确输出信息,cmd文件中必须指定heap的大小,即cmd文件这样写: -c -stack 0x00001000 /* Stack Size */ -heap 0x00001000 /* Heap Size */ //前面这三项必不可少 MEMORY { L2RAM: o = 0x10800000 l = 0x00020000 DDR2: o = 0x80000000 l = 0x10000000 } SECTIONS { .bss > L2RAM .cinit > L2RAM .cio > L2RAM .const > L2RAM .data > L2RAM .far > L2RAM .stack > L2RAM .switch > L2RAM .sysmem > L2RAM .text > L2RAM .ddr2 > DDR2 }

C语言上机程序调试功能键及常见错误提示

C语言上机程序调试功能键及常见错误提示 1.常用健 : 激活系统菜单 : 将光标在编辑窗口和、信息窗口之间切换 : 加载一个文件 +: 查看程序运行结果 : 得到有关编辑器在线帮助 + : 得到有关C语言的在线帮助 +: 终止正在运行的程序 2.块操作 KB: 定义块首 KK: 定义块尾 KV: 块移动 KC: 块复制 KY: 块删除 KH: 取消块定义 3.查找、替换和删除操作 QF: 查找字符串 QA: 查找并替换字符串 Option: G(全程), B(向文件头), N(直接替换) Y : 删除一行 QY: 删除从光标位置到行末的所有字符 4.编译中的常见错误 (1)警告类错误 ?‘XXX’declare but never used变量XXX已定义但从未用过。 ?‘XXX’is assigned a value which is never used变量XXX已赋值但从未用过。?Code has no effect 程序中含有没有实际作用的代码。 ?Non-portable pointer conversion不适当的指针转换,可能是在应该使用指针的 地方用了一个非0的数值。 ?Possible use of ‘XXX’before definition表达式中使用了未赋值的变量 ?Redeclaration of ‘main’一个程序文件中主函数main不止一个。 ?Suspicious pointer conversion可疑的指针转换。通常是使用了基本类型不匹配的指针。 ?Unreachable code程序含有不能执行到的代码。 (2)错误或致命错误 ?Compound statement missing } in function main程序结尾缺少括号}。 ??}?expected;?(?expected等复合语句或数组初始化的结尾缺少?)?;?(?。? Case outside of switch case不属于Switch结构,多由于switch结构中的花括 号不配对所致。 ?Case statement missing ‘:’ switch结构中的某个case之后缺少冒号。 ? Constant expression required定义数组时指定的数组长度不是常量表达式。 ? Declaration syntax error 结构体或联合类型的定义后缺少分号。

PLC程序现场调试的方法

P L C程序现场调试的方法 Prepared on 24 November 2020

PLC程序现场调试的方法——【非常重要】 02-04 16:42更新林慧玲分类:围观:625人次微信二维码 1、要查接线、核对地址 要逐点进行,要确保正确无误。可不带电核对,那就是查线,较麻烦。也可带电查,加上信号后,看电控系统的动作情况是否符合设计的目的。 2、检查模拟量输入输出 看输入输出模块是否正确,工作是否正常。必要时,还可用标准仪器检查输入输出的精度。 3、检查与测试指示灯 控制面板上如有指示灯,应先对应指示灯的显示进行检查。一方面,查看灯坏了没有,另一方面检查逻辑关系是否正确。指示灯是反映系统工作的一面镜子,先调好它,将对进一步调试提供方便。 4、检查手动动作及手动控制逻辑关系 完成了以上调试,继而可进行手动动作及手动控制逻辑关系调试。要查看各个手动控制的输出点,是否有相应的输出以及与输出对应的动作,然后再看,各个手动控制是否能够实现。如有问题,立即解决。 5、半自动工作 如系统可自动工作,那先调半自动工作能否实现。调试时可一步步推进。直至完成整个控制周期。哪个步骤或环节出现问题,就着手解决哪个步骤或环节的问题。 6、自动工作 在完成半自动调试后,可进一步调试自动工作。要多观察几个工作循环,以确保系统能正确无误地连续工作。 7、模拟量调试、参数确定 以上调试的都是逻辑控制的项目。这是系统调试时,首先要调通的。这些调试基本完成后,可着手调试模拟量、脉冲量控制。最主要的是选定合适控制参数。一般讲,这个过程是比较长的。要耐心调,参数也要作多种选择,再从中

选出最优者。有的PLC,它的PID参数可通过自整定获得。但这个自整定过程,也是需要相当的时间才能完成的。 8、完成上述所有的步骤 整个调试基本算是完成了。但最好再进行一些异常条件检查。看看出现异常情况或一些难以避免的非法操作,是否会停机保护或是报警提示。进行异常检查时,一定要充分考虑到设备与人身的安全! 整个调试基本算是完成了。但最好再进行一些异常条件检查。看看出现异常情况或一些难以避免的非法操作,是否会停机保护或是报警提示。进行异常检查时,一定要充分考虑到设备与人身的安全!

C语言程序编辑或调试中常见的错误

常见错误和程序分析 (1)忘记定义变量。例如: void main() { x=3; y=6; printf(“%d\n”,x+y); } C要求对程序中用到的美一个变量都必须定义其类型,上面程序中没有对x,y 进行定义。应在函数体的开头加int x,y; (2)输入输出的数据类型与所用格式说明符不一致。例如,若a已定义为整数,b已定义为实型: a=3;b=4.5; /*对a和b赋值*/ printf(“%f %d\n”,a,b); 编译时不给出出错信息,但运行结果将与原意不符,输出为0.000000 16402它们并不是按照赋值的规则进行转换(如把4.5转换为4),而是将数据在存储单元中的形式按格式符的要求组织输出(如b占4个字节,只把最后2个字节中的数据按%d作为整数输出)。 (3)未注意int型的数据的数值范围。Turbo C等编译系统,对一个整型数据分配2个字节。因此一个整数的范围为-2的13次方到2的15次方减1,即-32768~32767常见这样的程序段: int num; num=89101; printf(“%d”,num); 得到的却是23565,原因是89101已超过32767。2个字节容纳不下89101,则将高位截去,即将超过低16位的数截去,也即89101-65536=23565,有时还会出现负数。这种情况应改为: Long int num; num=89101; printf(“%ld”,num); 注意,如果只定义num为long型,而在输出时扔用%d说明符,也会出现以上错误。 (4)在输出语句scanf中忘记使用变量的地址符。例如: scanf(“%d%d”,a,b); 这是很多初学者刚学C语言时常见的疏忽,应写为scanf(“%d%d”,&a,&b); (5)输入数据的形式与要求不符。例如有以下scanf函数: scanf(“%d%d”,&a,&b); 有人输入 3 , 4 ,这是错的数据间应该用空格来分隔,读者可以用printf(“%d%d”,a,b);来验证下。应该输入 3 4,除非函数是scanf(“%d,%d”,&a,&b); 还应注意不能企图用

VB程序调试技巧

一,如果遇到了一些逻辑性很强的问题比如有循环什么的我的方法是在关键地方加入debug.print 变量 这样可以比较好地找到问题 二,msgbox 三,监视窗口,如下面的例子 For i=1 to 10000 A=sqr(i) next i 你想再监视当i=799时A的值,就可以添加监视,方法:点调试,添加监视,选择“当监视值为真时中断”,上面表达式框中写上i=799, 这样你按F5,运行程序,程序会在i=799时中断。其他选项你可以自己去琢磨一下。 一个程序如何顺利的“脱产”,调试的过程是非常重要的。学过、钻研过程序设计的人都有同样的感受,很多情况下,调试程序的过程会比程序编写的过程更为困难。任何一个天才都不敢说,他编的程序是100%正确的。几乎每一个稍微复杂一点的程序都必须经过反复的调试、修改,最终才完成。所以说,程序的调试是编程中的一项重要技术。 程序中的典型错误类型 A类:语法错误。 B类:编译错误。 C类:属性设置错误。 D类:逻辑错误。 调试方法 方法一:利用“MSDN帮助菜单” “MSDN帮助菜单”是一个很好的自学工具,对于出现调试对话框的菜单来说,可以按下“帮助”按钮查看错误原因。 对于一些不是很清楚的函数格式、保留字的作用,也可以借助“帮助菜单”。 方法二:逐过程检查 主要检查代码是否写对,位置有没有错误,关键是要确定一段代码是在哪个事件控制下的。不妨先在脑海中把整个程序过一边,想一想究竟会有哪些事件发生(有些事件是人机互动的,例如:鼠标点击;而有些是机器自己执行的,这时要想到计时器的作用);然后想一想每一件事发生后有什么效果。我们代码所编写的一般就是事件发生后的这个效果,那么以此事件来决定代码所写的位置。 方法三:逐语句检查(顺序、语义) 主要检查每一句代码的顺序是否写对,语义是否正确。 把整个代码从头至尾地读一边,仔细思索每一段子过程什么时候执行,以及每一子过程中的每一句代码什么时候发生,必要时可以在程序段中插入Print语句分段查看;也可用注释语

C语言调试功能以及常见错误提示详解

C语言编译环境中的 调试功能及常见错误提示 调试功能 1.常用健 : 激活系统菜单 : 将光标在编辑窗口和、信息窗口之间切换 : 加载一个文件 + : 查看程序运行结果 : 得到有关编辑器在线帮助 + : 得到有关C语言的在线帮助 + : 终止正在运行的程序 2.块操作 KB: 定义块首 KK: 定义块尾 KV: 块移动 KC: 块复制 KY: 块删除 KH: 取消块定义 3.查找、替换和删除操作 QF: 查找字符串 QA: 查找并替换字符串 Option: G(全程),B(向文件头),N(直接替换) Y : 删除一行 QY: 删除从光标位置到行末的所有字符 编译中的常见错误例析 (1) 警告类错误 …XXX?declare but never used变量XXX已定义但从未用过。 …XXX?is assigned a value which is never used变量XXX已赋值但从未用过。 Code has no effect 程序中含有没有实际作用的代码。 Non-portable pointer conversion不适当的指针转换,可能是在应该 使用指针的地方用了一个非0的数 值。 Possible use of …XXX?before definition表达式中使用了未赋值的变量 Redeclaration of …main?一个程序文件中主函数main不止一个。 Suspicious pointer conversion可疑的指针转换。通常是使用了基本类型不匹配的指针。 Unreachable code程序含有不能执行到的代码。 (2) 错误或致命错误 Compound statement missing } in function main程序结尾缺少括号}。

调试与错误处理

第9章调试与错误处理 一、问答题 1.请思考如何避免错误。 答:1)事先精心设计应用程序,描述清楚相关事件以及代码响应每一事件的方法,为每一事件过程和每个普通过程都指定一个特点的、明确的目标。 2)多加注释。如果用注释说明每个过程的目的,在以后分析代码时,能更深入地理解这些代码。 3)对过程中用到的每个变量或对象都应该在过程开始部分加以定义。 4)在应用程序中对变量和对象提出一种前后一致的命名方案。 2.请简要设计错误处理程序的三个步骤。 答:1)捕获错误,并强制程序跳转 2)编写错误处理程序 3)退出错误处理程序 3.简述常用的程序调试技巧。 答:1)事先做好备份; 2)分离受怀疑的程序; 3)缩小搜索范围; 4)使用MsgBox语句。 4.简要说明VB程序调试的主要方法和工具。 答:VB 程序调试的主要方法:用编译器提示错误;使用调试工具来发现和改正错误;采用常用的调试技巧,如事先做好备份,分离受怀疑的程序,缩小搜索范围,使用MsgBox语句等。 主要工具:“调试”菜单下的“逐语句”、“逐过程”、“跳出”、“运行到光标处”、“添加监视”、“快速监视”、“切换断点”等子菜单项。 5.VB程序错误大体可分为哪几种,它们的含义是什么? 答:VB程序错误大体分为三种:编译错误、实时错误和语法错误。 编译错误是在编写程序时书写了有错误的语法的代码,导致VB编译器无法正确解释源代码而产生的错误,也称语法错误。实时错误是指在运行期间,一跳语句试图执行一条不可能执行的操作而产生的错误,也称运行时错误。逻辑错误是指程序的运行结果和程序员的设想有出入时产生的错误。 6.请说明On Error GoTo 与On Error Resume Next 的区别。 答:On Error GoTo 行标识符语句:当发生错误时,使用该语句强制改变程序的执行方向。而On Error Resume Next 语句:当发生错误时,VB程序将忽略引发错误的语句,并继续执行下一条语句。 二、程序设计题 1.程序改错。以前面学到的冒泡排序算法为例,开发以下程序,请上机练习排除其中的错误。 1

STM 调试过程中常见的问题及解决方法

一、在“Debug选项卡”下设置好仿真器的类型后,下载程序时却提示“No ULINK Device foun d.” 解决办法:Keil MDK默认使用ULINK仿真器下载程序,在“Utilities选项卡”下把编程所使用的仿真器改为相应的类型即可。 二、编译工程时提示如下信息: main.axf: Error: L6218E: Undefined symbol __BASEPRICONFIG (referred from stm32f10 x_nvic.o). main.axf: Error: L6218E: Undefined symbol __GetBASEPRI (referred from stm32f10x_nvi c.o). main.axf: Error: L6218E: Undefined symbol __RESETFAULTMASK (referred from stm32f 10x_nvic.o). main.axf: Error: L6218E: Undefined symbol __RESETPRIMASK (referred from stm32f10x _nvic.o). main.axf: Error: L6218E: Undefined symbol __SETFAULTMASK (referred from stm32f10x _nvic.o). main.axf: Error: L6218E: Undefined symbol __SETPRIMASK (referred from stm32f10x_n vic.o). 解决办法:工程缺少“cortexm3_macro.s”文件,把cortexm3_macro.s和STM3210x.s全部添加到工程即可。 三、调试器不能连接到STM32的问题与解决办法 很多人都碰到过调试器不能连接到STM32的问题,不管是IAR的J-Link还是Keil的ULink,或者是ST的ST-Link。出现这个问题时,调试软件会提示不能建立与Cortex-M3的连接,或提示不能下载程序,或提示找不到要调试的设备等。 这样的问题都是发生在调试那些可以在CPU不干预的时候自动运行的模块、或在调试低功耗模式的程序的时候。所谓“可以在CPU不干预的时候自动运行的模块”包括:DMA、定时器、连续转换模式下的ADC、看门狗等模块。 -------------------------------------------------------------------------------- 这个问题的根源是: 1. 调试器需要在RAM内执行一段程序,对Flash进行擦写操作,如果不停止这些自动运行的模块,它们会干扰程序在RAM中的执行,致使下载失败。比如DMA模块被配置为不停地拷贝一段数据区,而调试器刚好需要使用DMA数据传输的目标区域,这时DMA的操作将会与调试器的操作发生冲突。再比如,如果启动了看门狗而没有执行硬件复位,则在下次调试器需要下载程序时,看门狗超时将触发芯片复位,导致下载操作失败。 2. 低功耗是通过停止CPU的时钟而实现,JTAG调试是通过与CPU的通信实现,停止了C PU的时钟致使调试器会失去与CPU的通信。 --------------------------------------------------------------------------------

程序调试步骤

一、认识调试功能 在组建(build)菜单中,点击开始调试(start debug),在其下级子菜单中,包含了启动调试器运行的各项子命令(如图1所示) 图1 开始调试菜单 各子命令及其功能如下: ?Go:从程序中的当前语句开始执行,直到遇到断点(后面讲)或遇到程序结束。 ?Step Into:控制程序单步执行,并在遇到函数调用时进入函数内部。 ?Run to Cursor:在调试运行程序时,使程序运行到当前光标所在位置时停止,相当于设置了一个临时断点。 二、单步调试代码 利用图1菜单中的Step into功能或按F11键,进入单步调试状态,有一个箭头指向程序的第一行,每按一次F11键,程序再向前执行一行语句,如图2所示。

图2 开始调试后的界面 我们对图2的界面进行观察。 首先,菜单中增加一个调试(debug)菜单,如图中①处,下面是菜单中的部分功能(鼠标浮到上面时,会有提示,请试一试。) ?Step Into(F11):单步调试程序,遇到调用函数时,进入函数内部逐步执行; ?Step Over(F10):也是单步调试程序,遇到调用函数时,并不进入函数内容执行; ?Step Out:调试程序时,从正在执行的某个嵌套结构的内部跳到该结构的外部,常用于知道调用函数中不存在错误的情况; ?Run to Cursor(CTRL-F10):调试程序时,直接运行到插入点处。 其次,和当前正在执行的语句相关的变量,以及其当前的值显示在了②处。 再次,黄色箭头代表了正在执行的位置。 【练习1】 下面,针对求1+2+3+...+100的程序,体验单步执行。步骤: (1)编写如图所示求1+2+3+...+100的程序,排除编译错误; (2)按前述开始单步执行,用“Step Into(F11)”持续执行,在执行过程中,注意观察变量的变化。 ?调试中,要将自己的预期和计算机执行的结果进行比较,当发现不一致,恭喜,问题找到了。

Aleader--AOI-调试步骤与技巧

A l e a d e r--A O I-调试步骤 与技巧 -标准化文件发布号:(9556-EUATWK-MWUB-WUNN-INNUL-DDQTY-KII

标准注册与调试步骤 1.标准注册: A.电容: 电容的检测主要是检查其焊点、是否贴有元件和是否错料 电容命名格式是C-元 件大小-数字,eg:如图的 电容c0603-1 选定位框定位,框住 本体,便于找位 0603的元件偏移范围在之间, 若偏移范围过大,会导致测试 过程中框偏移而影响测试 注册时规定其中一个焊盘朝右 为零度,若当时元件不是按如图 所示的放置,则按此键旋转,使 B.电阻: 电阻的标准分两部分作,第一部分是看焊点(如下图图一),每二部分是看丝印(如下图图二),这样既可以检测焊点又可以检测是否错料(丝印检测) 电容命名格式是R-阻值(即本体 上的丝印),若同一块PCB板有大 小不同、阻值相同的元件,则R- 阻值-元件大小 焊点检测时不用滤色功能和调 整对比度、亮度 在上面的选项都选择完后,点 击此按钮,确定注册 图一

丝印的变化较多,若与本体 一起作标准,则影响焊点的 检测,且误判较多,很难调顺, 单独对丝印作标准,可以减 少由于丝印变化而带来的误 偏移范围一般填 作丝印检测时通过滤色可以消除 松香对丝印的影响,调整对比度和 亮度可使白的部分更白黑的更黑, 图二 C.三极管: 三极管的的标准分三部分作,具体步骤如下: ⑴本体和两个脚一起框,主要用来检测两个脚的焊点,加上本体能更好定位,编程时若三极管来料较多,都可以用一个来替换,可以节约编程时间,且在调试时可以不考虑丝印对它的影响,只要看焊点是否完好,而检测错料可以对丝印单独作标准{见第 三极管的命名格式是Q-数字,允 许偏移范围一般在加上极性检测 后能更好地检测元件是否贴反,定 位框定位能更准确找位 不管元件原来在PCB板的 放置如何,注册标准时一定 要将焊盘朝右,按此按钮可 以实现

Visual C++6.0中的调试工具使用及常见错误

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、忘记在语句的末尾加分号,或在预处理命令后多加分号。记住:每一个语句的后边都要 加分号,而预处理命令并不是语句,所以不加分号,他们必须每行一条,不能把多个命

相关文档