How to detect Runtime Errors in PASCAL

Write here if you have problems with your Pascal source code

Moderator: Board moderators

Post Reply
lost
New poster
Posts: 11
Joined: Wed Oct 04, 2006 9:16 pm

How to detect Runtime Errors in PASCAL

Post by lost » Fri Oct 06, 2006 1:20 pm

I had several very unpleasant experiences with Runtime Errors (RE) being reported as Wrong Answer (WA).

Reason for those is mentioned in post about 'submitting Pascal'. It turns out that FPC does not emit error signal (at least not under Linux), so if RE occurs your program either just abort, leaving your result output unfinished (and thus producing WA), or it write few error strings and then abort, which again result in WA since those error strings were not expected in output.

But fact that we know WHY it happens does not change fact that it is very annoying when it happens - getting WA instead of RE can result in significant waste of time before you realise that it was RE. Especially for those of us who program and test on different compiler than one run by judge. For example, I use Delphi, and when i suspect some compiler-related issue i test on Windows/DOS version of FPC, but neither of those is same as Linux one run by judge.

I made work-around solution to help me in such cases, and it is basically turning RE into Timeout Errors (TE) instead of WA. Since I made it as block of code that I can include in all my solutions, I decided to post it here and potentially help some of pascal users out here
Last edited by lost on Fri Oct 06, 2006 1:43 pm, edited 1 time in total.

lost
New poster
Posts: 11
Joined: Wed Oct 04, 2006 9:16 pm

Post by lost » Fri Oct 06, 2006 1:26 pm

ok, here is code:

Code: Select all


// to test for runtimes errors (RE) and turn them to TimeOuts
// hints: do not use inc/dec in your program (they skip R+)
{$DEFINE RE_CHK}

{$IFDEF RE_CHK}
{$Q+} // integer overflow checking $Q+
{$R+} // range checking $R+
{$S+} // stack checking $S+
{$ENDIF}

uses sysutils;


// wait more that 50sec - result in TE
function doMyError:longint
var a,b,res: longint;
begin
  res:=0;
  for a:=1 to 500 do
    for b:=1 to 2500000 do
      if odd(a) then res:=res+round(sqrt(a))
                   else res:=res-round(sqrt(a));
  doMyError:=res;
end;

procedure myError(a:longint; p1,p2: pointer); 
begin  
  doMyError; 
end;
procedure myExcept(t:TObject; p: pointer; l:longint; pp:PPointer); 
begin   
  doMyError; 
end;


//main program body
BEGIN
  {$IFDEF RE_CHK}
  exceptproc:=@myExcept;
  errorProc:=@myError;
  {$ENDIF}

  // here goes rest of your code....

END.

Last edited by lost on Fri Oct 06, 2006 1:40 pm, edited 1 time in total.

lost
New poster
Posts: 11
Joined: Wed Oct 04, 2006 9:16 pm

Post by lost » Fri Oct 06, 2006 1:33 pm

If you do not want to use Runtime error check, just remove define for RE_CHK - that should be your default.

If you get WA that you suspect might be RE in disguise, just define RE_CHK and resubmit ...if you now get TE instead of WA, it was RE !

Above approach turns on compiles checks for range, stack and integer overflow. Without those, FPC could just have undefined behaviour (like aborting without any error). With those turned on, errors/exceptions will be catched with those two procedures, and will result in timeout loop.

Note that some situations in FPC will not result in range checking errors, even if they result in Deplhi. For example, FPC does not check for range in INC or DEC commands, so avoid using them. Instead of inc(a) use usual a:=a+1; something I find hard to get used to, but... ;p

One often reason for RE related to range is default integer size of FPC used by judge, which is not guaranteed to be 32 bits like in Delphi. Use longint instead of integers to avoid this.

Post Reply

Return to “Pascal”