Manual
Errors
 previous   up   next 

17. ERRORS

17.1 Parsing errors

Parsing errors are triggered by interpreter and compiler. The checks for these errors are done before the program is executed respectively compiled. The errors do not terminate parsing except for error 1 (Out of heap space). If there are errors the program cannot be interpreted respectively compiled. The interpreter option -x can be used to execute even if the program contains errors. The following parsing 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" (U+%04x)
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: Illegal string escape "\%s"
22: Numerical escape sequences should end with ";" not "%s"
23: The numerical escape sequence "\%u;" is too big
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: Redeclaration of "%s"
35: Previous declaration of "%s"
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: Syntax %s declared twice
41: Dot expression expected as syntax description, found %s
42: "%s" redeclared with infix priority %d not %d
43: "%s" redeclared with prefix priority %d not %d
44: Priority %d required for parameter after "%s" not %d
45: Priority <= %d expected found "%s" with priority %d
46: "%s" must have priority %d not %d for dot expression
47: "%s" expected found "%s"
48: Undefined type for literal "%s"
49: Kind of in-parameter (val or ref) unspecified for type "%s"
50: "newtype", "subtype", "func", "enumlit" or "action" expected found "%s"
51: "func" or "type" expected found "%s"
52: Match for %s failed
53: Variable expected in %s found %s
54: Type expected found %s
55: Procedure expected found %s expression
56: Parameter specifier expected found "%s"
57: Evaluate type expression %s failed
58: Overlong UTF-8 encoding used for character "%s" (U+%04x)
59: UTF-16 surrogate character found in UTF-8 encoding "%s" (U+%04x)
60: Non Unicode character found "%s" (U+%04x)
61: UTF-8 continuation byte expected found "%s" (U+%04x)
62: Unexpected UTF-8 continuation byte found "%s" (U+%04x)
63: Solitary UTF-8 start byte found "%s" (U+%04x)
64: UTF-16 byte order mark found "%s" (U+%04x)
65: Use / instead of \\ as path delimiter
Undefined error

17.2 Compilation errors

The compiler does checks when generating code. As a result of the checks some warnings might be written. The warning level can be specified with the option -wn

Level Warning
2 Comparison with %s always evaluates to %s.
2 Expression raises "%s".
1 Catch of "%s" although the checks are suppressed.
1 Catch of otherwise although the checks for %s are suppressed.
1 Duplicate when values %s.
1 Previous usage of %s.
1 When value must be constant.
1 Forward defined function called.
1 Forward definition of the called function.

17.3 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. If no corresponding exception handler exists the program is terminated. There are various exceptions, which can be raised: MEMORY_ERROR, NUMERIC_ERROR, OVERFLOW_ERROR, INDEX_ERROR, RANGE_ERROR, FILE_ERROR, DATABASE_ERROR, GRAPHIC_ERROR and ILLEGAL_ACTION. A program can raise an exception with the raise statement. For example:

raise RANGE_ERROR;

Additional exceptions can be declared with:

const EXCEPTION: MY_ERROR is enumlit;

17.3.1 MEMORY_ERROR

The exception MEMORY_ERROR is raised if 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.

17.3.2 NUMERIC_ERROR

The exception NUMERIC_ERROR is raised if 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:

17.3.3 OVERFLOW_ERROR

An integer overflow occurs if a calculation produces a result that cannot be stored in an integer variable. This happens if 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. If an overflow situation occurs, although overflow checking has been switched off (with -so), the behavior is undefined (see chapter 17.6 Suppressing exception checks).

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 behavior. The overflow concept of Seed7 has been designed to allow, that simple C code is generated, if 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

If 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, if 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 if there is an alternate way to return the correct result.

17.3.4 INDEX_ERROR

An INDEX_ERROR occurs if an index is used to access an array, string, bstring or ref_list element beyond the elements that actually exist. E.g. An attempt to get an element of a string, bstring or ref_list with a negative or zero index raises INDEX_ERROR.

It may be raised from the following array operations:
[index], [index ..], [.. index], [start .. stop], [index len length], insert, remove.
It may be raised from the following string operations:
[index], [index ..], [.. index], [start .. stop], [index len length], [index fixLen length], @:= [index] char, @:= [index] string.
It may be raised from the following bstring operation:
[index].
It may be raised from the following hash operations:
[.
It may be raised from the following ref_list operations:
[index], @:= [index] element.

The interpreter checks always if an index refers to an existing element. By default the compiler generates code to check if indices refer to an existing element. The option -si can be used to suppress the generation of index checks. If a nonexistent element is referred, although index checking has been switched off (with -si), the behavior is undefined (see chapter 17.6 Suppressing exception checks).

17.3.5 RANGE_ERROR

Many functions define a range of valid arguments and raise RANGE_ERROR if this range is violated.

It may be raised from the following boolean operations:
conv, parse, boolean, succ, pred, boolean, rand.
It may be raised from the following integer operations:
parse, radix, RADIX, sci, rand, integer, bytes, bytes2Int.
It may be raised from the following bigInteger operations:
parse, radix, RADIX, sci, rand, integer, bytes, bytes2BigInt, ord, bigInteger, bitLength, modInverse, modPow.
It may be raised from the following rational operations:
parse, digits, sci, rational.
It may be raised from the following bigRational operations:
parse, digits, sci, bigRational.
It may be raised from the following float operations:
parse, digits, sci, float, round, trunc, rand.
It may be raised from the following complex operations:
parse, digits, sci, complex.
It may be raised from the following char operations:
conv, parse, chr, char, rand, char, trimValue.
It may be raised from the following string operations:
mult, pos, rpos.
It may be raised from the following bitset operations:
conv, parse, rand, min, max, next, integer, bitset.
It may be raised from the following array operations:
times, rand.
It may be raised from the following bin32 operations:
radix, RADIX, bytes, float2MbfBits.
It may be raised from the following bin64 operations:
radix, RADIX, bin64, bytes, float2MbfBits.
It may be raised from the following category operations:
parse, category.
It may be raised from the following ref_list operations:
pos.
It may be raised from the following file operations:
open, openUtf8, openUtf16le, openUtf16be, openUtf16, openInetSocket, write, writeln, gets, length, truncate, seek, tell, skip.

17.3.6 FILE_ERROR

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

It may be raised by the following functions:
fileType, fileTypeSL, fileSize, bigFileSize, getFileMode, setFileMode, getATime, setATime, getCTime, getMTime, setMTime, getOwner, setOwner, getGroup, setGroup, readDir, removeFile, removeTree, moveFile, cloneFile, copyFile, readlink, symlink, hasNext, seek, tell, bigTell, setbuf, write, inetSocketAddress, inetListenerAddress, openInetSocket, openInetListener.

17.3.7 DATABASE_ERROR

The exception DATABASE_ERROR may be raised by database functions. If a DATABASE_ERROR is caught it is possible to get some information about the cause of the error with:

const func string: errMessage (DATABASE_ERROR)

There are messages coming from the database and from the Seed7 database driver. The database driver may have a message like:

Searching for dynamic libraries failed: libclntsh.so

This indicates that the connector library could not be found. In this case the environment variable LD_LIBRARY_PATH could be used to specify the place of the connector library.

17.3.8 GRAPHIC_ERROR

The exception GRAPHIC_ERROR may be raised by graphic drivers. If an underlying graphic library function reports an error a GRAPHIC_ERROR is raised.

17.3.9 ILLEGAL_ACTION

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

17.4 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 caught by the other handlers:

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

17.5 Trace exceptions

The interpreter option -te can be used to trace exceptions and handlers. If an exception occurs the following is written:

*** Exception NUMERIC_ERROR raised at integer.s7i(118)
{160000 div fuel_max } at lander.sd7(836)
*** Action "INT_DIV"

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

In detail:

17.6 Stack trace

If 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(118)
in init_display at lander.sd7(836)
in setup at lander.sd7(906)
in main at lander.sd7(1536)

The stack trace shows that a NUMERIC_ERROR was raised by the div operation. This operation is defined in line 118 of integer.s7i. More interesting is that div was called from the function 'init_display' in line 836 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 sigutl.c(218)

To get more information there are two possibilities:

If 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, if an uncaught exception occurs. This option allows debuggers to handle uncaught Seed7 exceptions. Note that -e sends the signal SIGFPE. This is done even if 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 if a crash occurs:

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

Program received signal SIGFPE, Arithmetic exception.
0x000000000041b942 in o_3912_init_display () at lander.sd7:839
839         fuel_gauge := 40 * rocket.fuel div fuel_max;
(gdb) bt
#0  0x000000000041b942 in o_3912_init_display () at lander.sd7:839
#1  0x000000000041c2e5 in o_3917_setup () at lander.sd7:908
#2  0x0000000000421fe1 in main (argc=1, argv=0x7fffffffdf28) 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 if an uncaught exception occurs. This allows the debugger to show a backtrace for uncaught Seed7 exceptions.

17.7 Suppressing exception checks

A Seed7 program can be compiled with the option -sx, to suppress the generation of checks for exceptions. The suppressed checks x are specified with letters from the following list:

If an exception situation occurs, although exception checking has been switched off (with -s), the behavior is undefined. In this case the following things can happen:

Undefined behavior is a term used in the language specification of C and in other programming languages. Undefined behavior usually means that the behavior of the program is unpredictable. Normally Seed7 has a well defined behavior in all situations. Even in situations where the language specification of C refers to undefined behavior.

A handler for an exception can only work reliable if the checks for the exception are done. The compiler warns if -s is used and there is a handler for an exception. e.g.:

*** example.sd7(123): Catch of OVERFLOW_ERROR although the checks are suppressed.

Only a program that never raises the specific exception and that does not have a handler for this exception can be considered to be compiled without checks for that exception. Careful program analysis and testing (the exception should never be raised) is necessary to decide about the omission of exception checking.

17.8 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, if 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 Raises exception Dialog to decide
SIGILL raise OVERFLOW_ERROR Raises exception Dialog to decide
SIGTRAP raise OVERFLOW_ERROR Raises exception Dialog to decide
SIGINT - Terminate with message Dialog to decide
SIGFPE raise NUMERIC_ERROR Raises exception Dialog to decide
SIGTERM - Terminate with message Terminate with message
SIGSEGV - Terminate program Terminate with message
SIGPIPE - Ignored Ignored
SIGWINCH Resize console - -
SIGALRM Wait for some time - -

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

If 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 if 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.

17.9 Other errors and warnings

No more memory. Parsing terminated.
This error message is displayed after the parsing 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 if 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 if the basic libraries are defined wrong.
Action $%s with empty value
This error can happen if an action tries to do something with NULL and NULL is not allowed as value. If parsing works correct this should never happen.
Action $%s requires variable %s not constant
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 if the basic libraries are defined wrong. Principally this error is possible with the following operations: :=, incr, decr, wrd_rd, lin_rd


 previous   up   next