Exceptions/Catch an exception thrown in a nested call: Difference between revisions
(added C++ implementation) |
No edit summary |
||
Line 235: | Line 235: | ||
Uncaught exceptions give information showing where the exception originated through the nested function calls together with the name of the uncaught exception, (U1) to stderr, then quit the running program. |
Uncaught exceptions give information showing where the exception originated through the nested function calls together with the name of the uncaught exception, (U1) to stderr, then quit the running program. |
||
=={{header|Tcl}}== |
|||
{{works with|Tcl|8.5}} |
|||
<lang tcl>package require Tcl 8.5 |
|||
proc foo {} { |
|||
set code [catch {bar} ex options] |
|||
if {$code == 1} { |
|||
switch -exact -- $ex { |
|||
U0 {puts "caught exception U0"} |
|||
default {return -options $options $ex ;# re-raise exception} |
|||
} |
|||
} |
|||
} |
|||
proc bar {} {baz} |
|||
# create an alias to pass the initial exception U0 to the baz proc |
|||
interp alias {} baz {} _baz U0 |
|||
proc _baz {exception} { |
|||
# re-set the alias so subsequent invocations will use exception U1 |
|||
interp alias {} baz {} _baz U1 |
|||
# throw |
|||
return -code error $exception |
|||
} |
|||
foo |
|||
foo</lang> |
|||
Running this program results in: |
|||
<pre>$ tclsh85 exceptions.tcl |
|||
caught exception U0 |
|||
U1 |
|||
while executing |
|||
"baz" |
|||
(procedure "bar" line 1) |
|||
invoked from within |
|||
"bar" |
|||
(procedure "foo" line 2) |
|||
invoked from within |
|||
"foo" |
|||
(file "exceptions.tcl" line 26)</pre> |
Revision as of 17:36, 16 April 2009
You are encouraged to solve this task according to the task description, using any language you may know.
Show how to create a user-defined exception and show how to catch an exception raised from several nested calls away.
- Create two user-defined exceptions, U0 and U1.
- Have function foo call function bar which then calls function baz.
- Arrange for function baz to raise, or throw exception U0 on its first call, then exception U1 on its second.
- Function foo should catch only exception U0, not U1.
Show/describe what happens when the program is run.
Ada
<lang ada>with Ada.Text_Io; use Ada.Text_Io;
procedure Exceptions_From_Nested_Calls is
U0 : exception; U1 : exception; Baz_Count : Natural := 0; procedure Baz is begin Baz_Count := Baz_Count + 1; if Baz_Count = 1 then raise U0; else raise U1; end if; end Baz; procedure Bar is begin Baz; end Bar; procedure Foo is begin Bar; exception when U0 => Put_Line("Procedure Foo caught exception U0"); end Foo;
begin
for I in 1..2 loop Foo; end loop;
end Exceptions_From_Nested_Calls;</lang> Sample output:
Procedure Foo caught exception U0 raised EXCEPTIONS_FROM_NESTED_CALLS.U1 : exceptions_from_nested_calls.adb:13
An unhandled exception leads to termination of the corresponding task. When the task is the main task of the program as in the example, the whole program is terminated. In the example the exception back tracing message is compiler-specific (in this case it is GNAT and further depends on the compiler options.
C++
First exception will be caught and message will be displayed, second will be caught by the default exception handler, which as required by the C++ Standard, will call terminate(), aborting the task, typically with an error message.
<lang C++>
- include <iostream>
class U0 {}; class U1 {};
void baz(int i) {
if (!i) throw U0(); else throw U1();
} void bar(int i) { baz(i); }
void foo() {
for (int i = 0; i < 2; i++) { try { bar(i); } catch(U0 e) {
std::cout<< "Exception U0 caught\n";
} }
}
int main() {
foo(); std::cout<< "Should never get here!\n"; return 0;
} </lang>
Result:
Exception U0 caught This application has requested the Runtime to terminate it in an unusual way.
The exact behavior for an uncaught exception is implementation-defined.
D
First exception will be caught and message will be displayed, second will be caught by default exception handler.
<lang D> module test;
import tango.io.Stdout;
class U0 : Exception { this() { super("U0 error message"); } } class U1 : Exception { this() { super("U1 error message"); } }
void foo() {
for (int i = 0; i < 2; i++) { try { bar(i); } catch(U0 e) { Stdout ("Exception U0 caught").newline; } }
}
void bar(int i) { baz(i); } void baz(int i) {
if (!i) throw new U0; else throw new U1;
}
void main() { foo(); } </lang>
Result:
Exception U0 caught test.U1: U1 error message
If you have tango stack-trace, stack-trace will be print after second message.
Java
Methods that may throw an exception (or that call a method that may throw an exception that it does not catch) must explicitly declare that they can throw such an exception (or a superclass thereof), unless they are unchecked exceptions (subclasses of RuntimeException
or Error
):
<lang java>class U0 extends Exception { }
class U1 extends Exception { }
public class ExceptionsTest {
public static void foo() throws U1 { for (int i = 0; i <= 1; i++) { try { bar(i); } catch (U0 e) { System.out.println("Function foo caught exception U0"); } } }
public static void bar(int i) throws U0, U1 { baz(i); // Nest those calls }
public static void baz(int i) throws U0, U1 { if (i == 0) throw new U0(); else throw new U1(); }
public static void main(String[] args) throws U1 { foo(); }
}</lang> Sample output:
Function foo caught exception U0 Exception in thread "main" U1 at ExceptionsTest.baz(ExceptionsTest.java:23) at ExceptionsTest.bar(ExceptionsTest.java:16) at ExceptionsTest.foo(ExceptionsTest.java:8) at ExceptionsTest.main(ExceptionsTest.java:27)
The first line of the output is generated from catching the U0 exception in function foo.
Uncaught exceptions give information showing where the exception originated through the nested function calls together with the name of the uncaught exception, (U1) to stderr, then quit the running program.
OCaml
<lang ocaml>exception U0 exception U1
let baz i =
raise (if i = 0 then U0 else U1)
let bar i = baz i (* Nest those calls *)
let foo () =
for i = 0 to 1 do try bar i with U0 -> print_endline "Function foo caught exception U0" done
let () = foo ()</lang> Sample output:
Function foo caught exception U0 Exception: U1.
Python
There is no extra syntax to add to functions and/or methods such as bar, to say what exceptions they may raise or pass through them: <lang python>class U0(Exception): pass class U1(Exception): pass
def foo():
for i in range(2): try: bar(i) except U0: print "Function foo caught exception U0"
def bar(i):
baz(i) # Nest those calls
def baz(i):
raise U1 if i else U0
foo()</lang> Sample output:
Function foo caught exception U0 Traceback (most recent call last): File "C:/Paddy3118/Exceptions_Through_Nested_Calls.py", line 17, in <module> foo() File "C:/Paddy3118/Exceptions_Through_Nested_Calls.py", line 7, in foo bar(i) File "C:/Paddy3118/Exceptions_Through_Nested_Calls.py", line 12, in bar baz(i) # Nest those calls File "C:/Paddy3118/Exceptions_Through_Nested_Calls.py", line 15, in baz raise U1 if i else U0 U1
The first line of the output is generated from catching the U0 exception in function foo.
Uncaught exceptions give information showing where the exception originated through the nested function calls together with the name of the uncaught exception, (U1) to stderr, then quit the running program.
Tcl
<lang tcl>package require Tcl 8.5
proc foo {} {
set code [catch {bar} ex options] if {$code == 1} { switch -exact -- $ex { U0 {puts "caught exception U0"} default {return -options $options $ex ;# re-raise exception} } }
}
proc bar {} {baz}
- create an alias to pass the initial exception U0 to the baz proc
interp alias {} baz {} _baz U0
proc _baz {exception} {
# re-set the alias so subsequent invocations will use exception U1 interp alias {} baz {} _baz U1 # throw return -code error $exception
}
foo foo</lang> Running this program results in:
$ tclsh85 exceptions.tcl caught exception U0 U1 while executing "baz" (procedure "bar" line 1) invoked from within "bar" (procedure "foo" line 2) invoked from within "foo" (file "exceptions.tcl" line 26)