FreePascal环境下程序调试注意事项

在FP环境下调试程序的注意事项
1. 调试前的几点注意事项

(1) 增加程序本身的稳定性
a) 静态查错
为了减少无谓的调试,这一步很重要。往往一个TP中很容易查出的错误,FP却要花费惨重的代价。
b) 很小的数据可以手工运算
就好比分区联赛初赛中的阅读程序写运行结果一样,一些低级错误尽量不要依靠调试来检查。

(2) 检查数组和数据的范围
FP中有些错误同TP一样,会提前报告,如:

错误类型 举例 报告信息
数组赋值越界 var a:array[1..10]of integer;begin a[0]:=0;end; Range check error while evaluating constants
数据赋值越界 Var x:integer;Begin x:=2147483647;End. Range check error while evaluating constants
但有些错误不会提前报错,如:Var a:array[x..y] of 基类型;下标p出现小于x或大于y的情况,如下:
var a:array[1..100] of integer;
i:integer;
begin
  fillchar(a,sizeof(a),0);
  i:=100;
  while a=0 do i:=i-1;
   write(a);
  readln
end.
这个程序在TP下运行没有问题,但在FP下就会出现201错误。原因是while循环结束后的i值是0,输出a[0]的值。
再比如,下面的这个求1~N的全排列的回溯法程序:
program p17a;
var

  stack:array[1..20] of integer;
  s:set of 0..20;
  j,top,k,n:integer;
begin
  readln(n);
  s:=[ ];
  top:=0;k:=0;
  while top>=0 do
    begin
      k:=k+1;
      if k>n then begin k:=stack[top];s:=s-[k];top:=top-1;end{回溯}
      else if not(k in s) then begin
         top:=top+1;
         stack[top]:=k;
         s:=s+[k];
         k:=0;
         if top=n then
           begin
             for j:=1 to top do write(stack[j]);
             writeln;
           end
      end
    end
end.
运行后输出结果正确,但会报201错误,只要把stack[1..20]改成[0..20]就OK了。

下面列出一些常见的蕴涵错误,大家必须当心:

错误类型 举例 造成影响
数据循环越界 Var x:integer;Begin For x:=1 to 32769 do Write(x);End. x既不是由1循环至32769,也不是由1循环到32767,而是由1循环至2。所以输出结果为:12
数组下标循环越界 Var i:integer; a,b:array[1..5]of integer;Begin For i:=1 to 5 do b:=i; For i:=1 to 6 do a:=i;End. 会不定性的出现两种情况:情况1:程序运行到a[6]:=6是出错中止,出现“000070E7 SYSTEM$$_HANDLEERRORADDRFRAME$LONG INT$LONG INT$LONGINT( )”等信息;情况2:a[6]:=6语句的出现会修改其它变量比如b[1]的值。这一点比较像Delphi5。
字符串长度越界 Var i:integer; S:string;Begin S:=’’; For i:=1 to 256 doS:=S+chr(i mod 10+48); Writeln(length(S)); Writeln(S);End. 对于超出长度范围上界的字符串部分,所有操作一律无效。输出结果为:2551234567890………………6789012345
集合范围越界 Var i:integer; S:set of 1..128;Begin S:=[1..10]; For i:=0 to 128 do If i in s then writeln(i);End. 虽然单独写入s:=[1..10]的语句,FP无任何不良反应,但程序运行到“if 0 in s then writeln(0)“时会出错终止,哪怕程序第3行写入的是语句s:=[0..10]也同样不能做if 0 in s的判断。还必须把集合的定义改成S:set of 0..128;
空间溢出 Var a:array[1..100000000]of longint;Begin ……End. FP不会提前报错,但一运行程序,就会因空间溢出而出错中止。

对于不会报告的错误,倘若是空间溢出等,虽然在调试过程中会出现挂机、莫名退出程序、跟踪光条消失种种问题,让人甚为恼火,但相比之下,数据循环越界、数组下标越界等FP自以为“兼容”的问题,却更加可怕。它们很隐蔽的潜藏起来,如果不加注意,只关心算法本身的正确性,会耗费很多调试程序的时间,这是不值得的。

(3) 把数组开小一点
若不然,FP会出现莫名其妙退出的现象,哪怕程序毫无错误。

(4) 编程过后要存盘。
存盘是当然,不然FP会报告"Can't compile unsaved file!"信息,以防止程序意外丢失。

2. 调试时的几点注意事项

(1) 模块调试
这种分治策略,针对FP IDE速度慢,而且Bug多的特点,降低了调试难度。

(2) 避免使用F7
F7经常失效,它往往拒绝进入子程序展开进一步的跟踪。这时,F4可以代替F7完成工作。切记这一点,不然在跳过子程序后再重头调试是很麻烦的。

(3) 减少F8的使用频率
虽然F8不象F7那样不听指挥,但也时常失效,尤其是在程序运行出错以后。

(4) 尽量使用F4
很多时候,F8会在程序出错再调试时出现一些随机给出的错误,比如说蓝条会消失,FPcx莫名退出,甚至死机。F4相对稳定一些,只不过当遇到类似If 、Case 语句时,最好看清楚了,程序会执行哪一步。

(5) ALT+F7会失效
对于这一点,似乎没有很好的补救措施,只能打开Run菜单,点击Parameter。

(6) 集合类型不能察看怎么办
这里有两条应对措施:
a) 简单的试题保证集合类型使用正确;
b) 繁琐的试题避免使用集合类型;

(7) 诡异的多维数组跟踪
在程序体中用a[i,j]和a[j]来访问数组都是正确的,但在watches中跟踪二维数组的一个单元时,就只能用a[j]来查看了。例如二维数组a[3,4]=10,在watches中跟踪a[3,4]看到的不是10,只有跟踪a[3][4],显示出来的才是10。

3. 出错后的几点应对措施
(1) 发现错误,想结束调试。
千万不要在修改测序后接着使用F8,因为FP不会理睬你对程序的修改,不会像TP 和Dlephi一样出现类似“Source hs been modified. Rebuild? Yes? No? Cancle”的对话框,还可能导致蓝条的消失。所以,使用快捷键CTRL+F2终止调试,然后使用快捷键ALT+F9进行编译,当然存盘不要忘记。

(2) 程序运行出错
使用ALT+F5察看黑屏上有无出错信息。
当你再次调试时,有时一切运行良好,但有时会出现一些问题:
a) 如果F8不工作了,那么再次存盘并使用Build编译;
b) 如果F8仍然不工作,那么尝试使用F4;
c) 如果蓝条消失,也可以尝试使用F4;
d) 如果F4也不工作,那么关闭其它窗口的程序,再尝试一次;
e) 如果F4仍然不工作,那么ALT+X关掉所有可以关闭的程序,并退出失控的FP, 然后重新进入。

4、其他
① Free Pascal在windows 95及其以上的windows版本上支持长文件名。对于文件名,由于windows系统对大小写不敏感,因此在程序中,文件名的大小写是无关的。但是对于其它大小写敏感的系统,比如linux,程序中用到的文件名必须和系统中的文件名完全一致。
由于信息学竞赛的评测系统一般是linux,因此要求程序中的文件名和系统中的文件名一样。即:比赛中涉及的所有文件名(包括源程序名、输入文件名、输出文件名、答案文件名),都必须严格按照题目要求命名,严格区分大小写。例如:题目要求输入文件名为game.in,则程序中必须按照该名字打开文件,不能使用Game.in、GAME.IN等名字;

② 在NOIP比赛中,程序中不得使用题目规定外的其他任何库(unit),一般在试机时确认;

③ 在NOIP比赛中,源代码中不得使用编译选项(开关);

④在NOIP比赛中,禁止使用meml进行掐时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值