Runtime errors
Runtime errors occur while a program is executing.
////////////////////////////////////////////////////////////////////////////////////////////////////
Common errors
1. an object receives a message which it doesn't understand
2. a binary operation (addition, subtraction, multiplication, etc.) can't be performed
3. a value other than true or false appears in a conditional (boolean) test
4. a file can't be opened (a primitive fails)
////////////////////////////////////////////////////////////////////////////////////////////////////
Object doesn't understand
In the case of
3.createRuntimeError
SuperCollider prints a four-part error notification to the post window. The parts of the notification are ERROR, RECEIVER, ARGS, and CALL STACK, as in
ERROR: Message 'createRuntimeError' not understood.
RECEIVER:
Integer 3
ARGS:
Instance of Array { (057E7560, gc=01, fmt=01, flg=11, set=00)
indexed slots [0]
}
CALL STACK:
DoesNotUnderstandError-reportError
arg this = <instance of DoesNotUnderstandError>
Nil-handleError
arg this = nil
arg error = <instance of DoesNotUnderstandError>
Object-throw
arg this = <instance of DoesNotUnderstandError>
Object-doesNotUnderstand
arg this = 3
arg selector = 'createRuntimeError'
arg args = [*0]
< closed FunctionDef > (no arguments or variables)
Interpreter-interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
Process-interpretPrintCmdLine
arg this = <instance of Main>
////////////////////////////////////////////////////////////////////////////////////////////////////
The ERROR section explains what went wrong. The RECEIVER section names the the class of the object to which the message was sent. The ARGS section says how many arguments were included in the message. Read the CALL STACK from the bottom to the top to see where the error happened. Reading from bottom to top means going from
Process-interpretPrintCmdLine
to
Interpreter-interpretPrintCmdLine
to
Object-doesNotUnderstand
to
Object-throw
to
Nil-handleError
to
DoesNotUnderstandError-reportError
which is the first line in the stack.
////////////////////////////////////////////////////////////////////////////////////////////////////
DoesNotUnderstandError-reportError
is the mechanism that prints the error notification to the post window. Select it and press cmd-j to see how it works (how it prints the notification).
////////////////////////////////////////////////////////////////////////////////////////////////////
Execute
$a * $b
to create another runtime error message.
////////////////////////////////////////////////////////////////////////////////////////////////////
The ERROR, RECEIVER, ARGS, and CALL STACK headers in the post window explain the problem: Instances of class Char have no knowledge of multiplication.
ERROR: Message '*' not understood.
RECEIVER:
Character 97 'a'
ARGS:
Instance of Array { (067F5470, gc=C4, fmt=01, flg=00, set=01)
indexed slots [1]
0 : Character 98 'b'
}
CALL STACK:
DoesNotUnderstandError-reportError
arg this = <instance of DoesNotUnderstandError>
Nil-handleError
arg this = nil
arg error = <instance of DoesNotUnderstandError>
Object-throw
arg this = <instance of DoesNotUnderstandError>
Object-doesNotUnderstand
arg this = $a
arg selector = '*'
arg args = [*1]
< closed FunctionDef > (no arguments or variables)
Interpreter-interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
Process-interpretPrintCmdLine
arg this = <instance of Main>
////////////////////////////////////////////////////////////////////////////////////////////////////
Unitialized variable (binary operation fails)
Here, the variable a is initialized to an integer and the variable b isn't initialized. Multiplying a (the integer 10) by b (nil, the value that SuperCollider uses for unitialized data) will create a runtime error.
(
var a = 10; // a is declared and initialized
var b; // b declared but not initialized, so it defaults to nil
t = Task({
4.do({ arg item, i;
if(i != 3)
{ i.postln } // print the value of i if it doesn't equal 3
{ (a * b).postln }; // when i equals 3, do a * b
// ... which is a problem if b is nil
1.wait;
})
});
t.start;
)
////////////////////////////////////////////////////////////////////////////////////////////////////
The printout shows the code ran successfully until the index, i, reached 3, which is when a * b happened. The ERROR, RECEIVER, ARGS, and CALL STACK headers describe the problem.
////////////////////////////////////////////////////////////////////////////////////////////////////
a Task
0
1
2
ERROR: binary operator '*' failed.
RECEIVER:
nil
ARGS:
Instance of Array { (067D92B0, gc=CC, fmt=01, flg=00, set=01)
indexed slots [2]
0 : Integer 10
1 : nil
}
CALL STACK:
DoesNotUnderstandError-reportError
arg this = <instance of BinaryOpFailureError>
Nil-handleError
arg this = nil
arg error = <instance of BinaryOpFailureError>
Object-throw
arg this = <instance of BinaryOpFailureError>
Object-performBinaryOpOnSomething
arg this = nil
arg aSelector = '*'
arg thing = 10
arg adverb = nil
Integer-*
arg this = 10
arg aNumber = nil
arg adverb = nil
< FunctionDef in closed FunctionDef >
arg item = 3
arg i = 3
Integer-do
arg this = 4
arg function = <instance of Function>
var i = 3
< FunctionDef in closed FunctionDef > (no arguments or variables)
Routine-prStart
arg this = <instance of Routine>
arg inval = 758.000000
////////////////////////////////////////////////////////////////////////////////////////////////////
True, false, or other
A value other than true or false in a boolean test, as in
if(x=4) { "this is ok"};
produces
ERROR: Non Boolean in test.
RECEIVER:
Integer 4
CALL STACK:
MethodError-reportError
arg this = <instance of MustBeBooleanError>
Nil-handleError
arg this = nil
arg error = <instance of MustBeBooleanError>
Object-throw
arg this = <instance of MustBeBooleanError>
Object-mustBeBoolean
arg this = 4
< closed FunctionDef > (no arguments or variables)
Interpreter-interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
Process-interpretPrintCmdLine
arg this = <instance of Main>
////////////////////////////////////////////////////////////////////////////////////////////////////
Correcting the test clause fixes the problem.
if(x==4) { "this is ok"};
////////////////////////////////////////////////////////////////////////////////////////////////////
Primitive fails
Asking for the length of a non-existent file creates a runtime error. The notification shows what went wrong (a C code primitive failed).
f = File("i_don't_exist", "r");
f.length;
ERROR: Primitive '_FileLength' failed.
Failed.
RECEIVER:
Instance of File { (067D9970, gc=C4, fmt=00, flg=00, set=01)
instance variables [1]
fileptr : nil
}
CALL STACK:
MethodError-reportError
arg this = <instance of PrimitiveFailedError>
Nil-handleError
arg this = nil
arg error = <instance of PrimitiveFailedError>
Object-throw
arg this = <instance of PrimitiveFailedError>
Object-primitiveFailed
arg this = <instance of File>
File-length
arg this = <instance of File>
< closed FunctionDef > (no arguments or variables)
Interpreter-interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
Process-interpretPrintCmdLine
arg this = <instance of Main>
////////////////////////////////////////////////////////////////////////////////////////////////////