Seed7 - The extensible programming language
Seed7 FAQ Manual Screenshots Examples Libraries Algorithms Download Links
Manual Introduction Tutorial Declarations Statements Types Parameters Objects File System Syntax Tokens Expressions OS access Actions Foreign funcs Errors
Errors Compile errors Exceptions Memory Error Numeric Error Overflow Error Range Error File Error Illegal Action Handlers Stack trace Signals Other errors
Manual
Errors
 previous   up   next 

15. ERRORS

15.1 Compile time errors

The compile time errors are not fatal (the program can execute) except for the error 1 (Out of heap space) which terminates the compilation process and no execution occurs. The following compile time errors exist:

1: Fatal Error: Out of heap space
2: File "%s" not found
3: Include file "%s" not found
4: "END OF FILE" encountered
5: Illegal character in text "%s"
6: Unclosed comment
7: Illegal pragma "%s"
8: Illegal action "%s"
9: Illegal system declaration "%s"
10: Integer "%s" too big
11: Negative exponent in integer literal
12: Digit expected found "%s"
13: Integer "%dE%s" too big
14: Integer base "%ld" not between 2 and 36
15: Extended digit expected found "%s"
16: Illegal digit "%c" in based integer "%d#%s"
17: Based integer "%d#%s" too big
18: "'" expected found "%s"
19: Character literal exceeds source line
20: Use \" instead of "" to represent " in a string
21: Use / instead of \\ as path delimiter
22: Illegal string escape "\%s"
23: Numerical escape sequences should end with ";" not "%s"
24: String continuations should end with "\" not "%s"
25: String literal exceeds source line
26: Name expected found "%s"
27: Integer literal expected found "%s"
28: String literal expected found "%s"
29: Identifier expected found "%s"
30: Expression expected found "%s"
31: Declaration of parameter %s failed
32: Declaration of "%s" failed
33: Exception "%s" raised
34: "%s" declared twice
35: "%s" not declared
36: Associativity expected found "%s"
37: Statement priority "%s" too big
38: Syntax with two parameters before operator is illegal
39: Empty syntax declaration
40: Dot expression requested as syntax description
41: "%s" redeclared with infix priority %d not %d
42: "%s" redeclared with prefix priority %d not %d
43: Priority %d required for parameter after "%s" not %d
44: Priority <= %d expected found "%s" with priority %d
45: "%s" must have priority %d not %d for dot expression
46: "%s" expected found "%s"
47: "%s" expected found "%s"
48: Undefined type for literal "%s"
49: "newtype", "subtype", "func", "enumlit" or "action" expected found "%s"
50: "func" or "type" expected found "%s"
51: Match for %s failed
52: Variable expected in %s found %s
53: Type expected found %s
54: Procedure expected found %s expression
55: Parameter specifier expected found "%s"
56: Evaluate type expression %s failed
57: Overlong UTF-8 encoding used for character "%s" (U+%04x)
58: UTF-16 surrogate character found in UTF-8 encoding "%s" (U+%04x)
59: Non Unicode character found "%s" (U+%04x)
60: UTF-8 continuation byte expected found "%s" (U+%04x)
61: Unexpected UTF-8 continuation byte found "%s" (U+%04x)
62: Solitary UTF-8 start byte found "%s" (U+%04x)
63: UTF-16 byte order mark found "%s" (U+%04x)
Undefined error

15.2 Exceptions

An exception is an anomalous event that arises during program execution. Exceptions change the normal flow of program execution. An exception transfers the execution to a corresponding exception handler. When no corresponding exception handler exists the program is terminated. There are various exceptions, which can be raised: MEMORY_ERROR, NUMERIC_ERROR, OVERFLOW_ERROR, RANGE_ERROR, FILE_ERROR and ILLEGAL_ACTION. A program can raise an exception with the raise statement. For example:

raise RANGE_ERROR;

15.2.1 MEMORY_ERROR

The exception MEMORY_ERROR is raised when there is not enough memory to store some data. This error can be raised from the run-time library or from the interpreter kernel. Catching a MEMORY_ERROR is possible, but it must be done with care. Variables involved in a MEMORY_ERROR may have an illegal value. A MEMORY_ERROR may be raised by various operations of the following types:

array, struct, hash, file, func, proc, reference, string.
Additionally the interpreter kernel may raise this exception also.

15.2.2 NUMERIC_ERROR

The exception NUMERIC_ERROR is raised when a numeric operation cannot deliver a correct result. This includes several things that are mathematically undefined such as division by zero, integer exponentiation with a negative exponent, square root of a negative number and logarithm of a negative number. NUMERIC_ERROR can be raised by operations of several types:

It may be raised from the following integer operations:
!, **, div, rem, mdiv, mod, sqrt, log2, log10.
It may be raised from the following bigInteger operations:
!, **, div, rem, mdiv, mod, sqrt, log2, log10.
It may be raised from the following rational operation:
/.
It may be raised from the following bigRational operation:
/.

In detail the following conditions can cause a numeric error:

15.2.3 OVERFLOW_ERROR

An integer overflow occurs when a calculation produces a result that cannot be stored in an integer variable. This happens when the result is less than integer.first or greater than integer.last.

It may be raised from the following integer operations:
- (sign), +, -, *, **, div, rem, mdiv, mod, <<, >>, +:=, -:=, *:=, <<:=, >>:=, !, abs, succ, pred, incr, decr.

In detail the following conditions can cause an overflow:

The interpreter checks always for an integer overflow. By default the compiler generates code to check for an integer overflow. The option -so can be used to suppress the generation of integer overflow checks. When an overflow situation occurs although overflow checking has been switched off (with -so) the behaviour is undefined. In this case the following things can happen:

  • The exception OVERFLOW_ERROR is still raised.
  • A different exception is raised.
  • The program hangs.
  • The program crashes.
  • The computation continues with some garbage value. This garbage value can then trigger dangerous things: The X-ray dosis computed by your program might be totally wrong. Your program might compute the statics of a bridge wrong.

Without integer overflow checks a handler for OVERFLOW_ERROR cannot work reliably. Only a program that does not have a handler for an OVERFLOW_ERROR exception can be considered to be compiled without overflow checks. Careful program analysis and testing (OVERFLOW_ERROR should never be raised) is necessary to decide about the omission of overflow checking.

The separate overflow exception allows easy recognition of overflow situations. All overflow situations, where OVERFLOW_ERROR is raised correspond to C situations, which have undefined behaviour. The overflow concept of Seed7 has been designed to allow, that simple C code is generated, when the overflow checks are switched off.

Compiler optimizations (e.g. with -oc2 or -oc3) can reduce the potential of overflow. In an optimized program an expression might be rephrased, such that an overflow is avoided and the correct result is computed instead. Consider the expression:

number + integer.last + integer.first

When number is between succ(integer.first) and 0 the expression can be evaluated and no overflow will occur. For other values of number the exception OVERFLOW_ERROR is raised. When the expression above is optimized it is rephrased to:

pred(number)

This expression only triggers OVERFLOW_ERROR, when number has the value integer.first.

With overflow checks it is guaranteed that an integer overflow always raises OVERFLOW_ERROR. But you cannot rely on OVERFLOW_ERROR being raised, when there is an alternate way to return the correct result.

15.2.4 RANGE_ERROR

A RANGE_ERROR occurs when an index is used to access an array or string element beyond the elements that actually exist. Many functions define a range of valid arguments and raise RANGE_ERROR when this range is violated.

It may be raised from the following boolean operations:
parse, rand.
It may be raised from the following integer operations:
parse, radix, RADIX, sci, rand, integer.
It may be raised from the following bigInteger operations:
parse, radix, RADIX, sci, rand, ord, bigInteger, bitLength, modInverse, modPow, .
It may be raised from the following rational operations:
parse, digits, sci.
It may be raised from the following bigRational operations:
parse, digits, sci.
It may be raised from the following float operations:
parse, digits, sci, rand, round, trunc.
It may be raised from the following complex operations:
parse, digits, sci.
It may be raised from the following char operations:
chr, rand.
It may be raised from the following string operations:
[, @:=, mult, pos, rpos.
It may be raised from the following bitset operations:
conv, parse, min, max, rand.
It may be raised from the following array operations:
[, times, remove, rand.
It may be raised from the following hash operations:
[.
It may be raised from the following bin32 operations:
radix, RADIX.
It may be raised from the following bin64 operations:
radix, RADIX.
It may be raised from the following category operations:
parse.
It may be raised from the following ref_list operations:
[, @:=, pos.
It may be raised from the following file operations:
open, write, gets, length, seek, tell.

15.2.5 FILE_ERROR

A FILE_ERROR occurs when an illegal operation with a file is done.

It may be raised by the following functions:
fileSize, bigFileSize, fileType, fileTypeSL, fileMode, setFileMode, readDir, removeFile, removeAnyFile, moveFile, cloneFile, copyFile, readlink, symlink, hasNext, seek, tell, bigTell, setbuf, write, inetSocketAddress, inetListenerAddress, openInetSocket, openInetListener.

15.2.6 ILLEGAL_ACTION

The exception ILLEGAL_ACTION may be raised by the interpreter kernel, when a primitive action does not point to any legal action. This check is only done when the s7 interpreter is compiled with '#define WITH_ACTION_CHECK'. The ILLEGAL_ACTION exception is also raised when the primitive action ACT_ILLEGAL is executed.

15.3 Handlers

To catch an EXCEPTION the following handler construct can be used:

block
  number := 1 div 0;
exception
  catch NUMERIC_ERROR:
    number := 1;
end block;

It is also possible to catch several EXCEPTIONS:

block
  doSomething(someValue);
exception
  catch MEMORY_ERROR:  writeln("MEMORY_ERROR");
  catch NUMERIC_ERROR: writeln("NUMERIC_ERROR");
end block;

An otherwise handler catches EXCEPTIONs, that are not catched by the other handlers:

block
  doSomething(someValue);
exception
  catch RANGE_ERROR: writeln("RANGE_ERROR");
  otherwise:         writeln("Any other exception");
end block;

15.4 Stack trace

When an EXCEPTION is not caught the program is terminated and the s7 interpreter writes a stack trace:

*** Uncaught EXCEPTION NUMERIC_ERROR raised with
{integer: <SYMBOLOBJECT> *NULL_ENTITY_OBJECT* div fuel_max }

Stack:
in (val integer: dividend) div (val integer: divisor) at integer.s7i(95)
in init_display at lander.sd7(840)
in setup at lander.sd7(909)
in main at lander.sd7(1541)

The stack trace shows that a NUMERIC_ERROR was raised by the div operation. This operation is defined in line 95 of integer.s7i. More interesting is that div was called from the function 'init_display' in line 840 of lander.sd7. A NUMERIC_ERROR with div is probably caused by a zero division. A short examination in lander.sd7 shows that an assignment to 'fuel_max' was commented out to show how stack traces work.

A compiled program creates a much shorter crash message:

*** Uncaught EXCEPTION NUMERIC_ERROR raised at tmp_lander.c(764)

To get more information there are two possibilities:

  • Start the program in the interpreter instead.
  • Compile the program with the options -g -e and start it from a debugger.

When s7c is called with the option -g it instructs the C compiler to generate debugging information. This way a debugger like gdb can run the program and provide information. The option -e tells the compiler to generate code which sends a signal, when an uncaught exception occurs. This option allows debuggers to handle uncaught Seed7 exceptions. Note that -e sends the signal SIGFPE. This is done even when the exception is not related to floating point operations.

./s7 s7c -g -e lander
gdb ./lander

Then the debugger should be able to run the program and to write a backtrace when a crash occurs:

(gdb) run
Starting program: /home/tm/seed7_5/prg/lander

Program received signal SIGFPE, Arithmetic exception.
0x08068518 in o_2541_init_display () at lander.sd7:840
840         fuel_gauge := 40 * rocket.fuel div fuel_max;
(gdb) bt
#0  0x08068518 in o_2541_init_display () at lander.sd7:840
#1  0x08068c21 in o_2546_setup () at lander.sd7:909
#2  0x0806c304 in main (argc=1, argv=0xbffff324) at lander.sd7:1541

Sometimes it is helpful to debug the generated C program instead of the Seed7 source. The option -g-debug_c creates debug information, which refers to the C program generated by the Seed7 compiler:

./s7 s7c -g-debug_c -e lander
gdb ./lander

Now the debugger refers to the temporary file tmp_lander.c:

(gdb) run
Starting program: /home/tm/seed7_5/prg/lander

Program received signal SIGFPE, Arithmetic exception.
0x08068518 in o_2541_init_display () at tmp_lander.c:19727
19727   o_2428_fuel_gauge=((40) * (((structType)(o_2338_rocket))->stru[10].value.intValue/*->o_2336_fuel*/)) / (o_2431_fuel_max);
(gdb) bt
#0  0x08068518 in o_2541_init_display () at tmp_lander.c:19727
#1  0x08068c21 in o_2546_setup () at tmp_lander.c:19864
#2  0x0806c304 in main (argc=1, argv=0xbffff324) at tmp_lander.c:21188

Some Seed7 exceptions do not send signals. This hinders the debugger to recognize that an uncaught exception occurred. The compiler option -e can help in this situation. It instructs the compiler to generate code which sends a signal when an uncaught exception occurs. This allows the debugger to show a backtrace for uncaught Seed7 exceptions.

15.5 Signals

A signal is an asynchronous notification of an event. The event can come from outside such as a request to terminate the program. The event can also come from the program itself such as a memory access violation (segfault). Several signals are handled by the Seed7 run-time library. The interpreter respectively compiler option -ts can be used to influence the behavior, when a signal is sent to a Seed7 program (see below). The following signals are handled by Seed7:

Signal Special handler Behavior without -ts Behavior with -ts
SIGABRT raise OVERFLOW_ERROR Terminate with message Dialog to decide
SIGILL raise OVERFLOW_ERROR Terminate with message Dialog to decide
SIGINT - Terminate with message Dialog to decide
SIGFPE raise NUMERIC_ERROR Terminate with message Dialog to decide
SIGTERM - Terminate with message Terminate with message
SIGSEGV - Terminate program Terminate with message
SIGPIPE - Ignore Ignore
SIGWINCH Resize console - -
SIGALRM Wait for some time - -

Depending on the actual C compiler and operating system the signals SIGABRT or SIGILL might be used to raise OVERFLOW_ERROR and the signal SIGFPE might be used to raise NUMERIC_ERROR.

When the interpreter respectively compiler option -ts has been used some signals (see table above) trigger a dialog at the console. E.g.:

*** SIGNAL SIGINT RAISED

*** The following commands are possible:
  RETURN  Continue
  *       Terminate
  /       Trigger SIGFPE
  !n      Raise exception with number (e.g.: !1 raises MEMORY_ERROR)

The user can enter a command and activate it with RETURN. If the program was waiting for an input at the console the input can be entered again:

re-enter input>

Triggering SIGFPE is useful when the program runs in a debugger. In this case SIGFPE will activate the debugger prompt. Raising an exception (e.g.: MEMORY_ERROR) can be used to get a stack trace (this works only in the interpreter). A compiled program must be executed with a debugger to get a stack trace.

15.6 Other errors and warnings

No more memory. Program terminated.
This error message is displayed after the compile time error 1 (Out of heap space) . The file name and line number of the analyzer source code where this happens is displayed together with internal heap information.
System declaration for main missing
Each program must contain a system declaration that describes which procedure to start as first one.
EXCEPTION %s raised with
If your trace level specifies exception tracing exceptions and handlers are displayed with this messages and the user must type the ENTER-key to accept.
ACTION $%s REQUIRES %s NOT %s
This error can happen when an action tries to do something with the wrong primitive value. For example adding an integer to a string with INT_ADD. Since the analyze phase checks for the right types this error can only happen when the basic libraries are defined wrong.
ACTION $%s REQUIRES VARIABLE %s NOT %s
This error can happen with actions which assign a value to a constant. Since the analyze phase checks for variable objects this error can only happen when the basic libraries are defined wrong. Principally this error is possible with the following operations: :=, incr, decr, wrd_rd, lin_rd


 previous   up   next