Forgotten exceptions or “finally dengerous”

February 9, 2012

Hello everyone! Today I gonna show you how to loose the exception in Java.

In fact Java exception mechanism has been implemented with “nothing could be missed” in mind, but there is a gap that permits simply “forget” an exception.

Consider the following example:

class MyException extends Exception {}

class ExceptionTester {
	public static void run() throws MyException {
		try {
			// Some actions here
		} finally {
			throw new MyException();
		}
	}

	public static void main( String[] args ) {
		try {
			run();
		} catch ( MyException e ) {
			e.printStackTrace( System.out );
		}
	}
}

We have static run() method that declared to throw MyException. In this method there is try-finally construction: the only purpose is to call finally {} block in any case (whether exception occurs or not). For simplicity, the finally block just throws MyException.

Workflow of this example is quite obvious: run() method is performed, then (after empty try {}) flow control goes to finally {} clause where MyException is thrown. The exception is caught in main’s catch() and stack trace is sent to stdout. Here is the output of the program:

$ java ExceptionTester                                                         
MyException                                                                                                                              
        at ExceptionTester.run(ExceptionTester.java:8)                                                                                   
        at ExceptionTester.main(ExceptionTester.java:14)

Now let’s put next code under run()‘s try block:

int a = 10 / 0;

so our run method becomes:

public static void run() throws MyException {
	try {
		int a = 10 / 0;
	} finally {
		throw new MyException();
	}
}

Yes, you are quite right: this is a division by zero, and we are all absolutely sure that Java will generate a java.lang.ArithmeticException. But just try to run the program again, and you will see the same output:

$ java ExceptionTester                                                         
MyException                                                                                                                              
        at ExceptionTester.run(ExceptionTester.java:8)                                                                                   
        at ExceptionTester.main(ExceptionTester.java:14)

So, where is our ArithmeticException? It is obviously that operation it was generated by occurred before our throw new MyException();. The culprit here is finally clause: it just replaced the ArithmeticException with MyException, hence we know nothing about invalid arithmetic operation in run() method into main(). It could be a real problem in big and complex systems: you’ll spend much time, trying to find out what had happened that MyException has been thrown and even not imagine that there was a ArithmeticException somewhere before.

You may argue that this is a gap in the architecture of particular application: try-finally block was used without catch clause. Yes it was. But it does what I want: I want to execute some code (throw new MyException in our case) every time the flow control leaves the run() method. But I don’t want to catch any exceptions on that level: I just don’t know what to do with them, so I delegate this activity moving catch clause off the run().

Now bad news: this is really gap in all Java pre 7th versions (including current stable 1.6.x).
Good news: this gap has been fixed in Java 7.

try-with-resources statement has been added in Java 7 to deal with try-finally issues. It looks like:

try( /* Construct the object that grabs some resources */ ) {
  // Do smth.
}
// Resources are relinquished


Object that “grabs resources” should implement AutoCloseable interface. Java automatically frees the resources by calling close() method each time the object goes out of try scope. The try-with-resources has additional feature: all exceptions from close() method of resource-grabber object are suppressed by exception from the try statement. So, if we have two exceptions: one from within try block, and another one from close() method, the last one will be suppressed by (and, as you can see later, included into) close-method exception.

At first, let’s define new class that implements AutoCloseable interface:

class MemoryReleaseError extends Exception {}

class ResourceGrabber implements AutoCloseable {
    ResourceGrabber() {
        System.out.println( "Let's grab some memory..." );
    }

    public void close() throws MemoryReleaseError {
        throw new MemoryReleaseError();
    }
}

The class grabs some resources into constructor and releases them into close() method. If something goes wrong here (in our case – everything is going wrong:)) – MemoryReleaseError will be thrown.

Now we could rewrite run() method from our example using “buggy” try-finally clause (I’ve also renamed it to buggyRun):

static void buggyRun() throws MemoryReleaseError {
    ResourceGrabber grabber = new ResourceGrabber();
    try {
        int i = 10 / 0;
    } finally {
        grabber.close();
    }
}

Also don’t forget to change run() to buggyRun() into main() method:

class MemoryReleaseError extends Exception {}

class ResourceGrabber implements AutoCloseable {
    ResourceGrabber() {
        System.out.println( "Let's grab some memory..." );
    }

    public void close() throws MemoryReleaseError {
        throw new MemoryReleaseError();
    }
}

public class ExceptionTester {
    static void buggyRun() throws MemoryReleaseError {
        ResourceGrabber grabber = new ResourceGrabber();
        try {
            int i = 10 / 0;
        } finally {
            grabber.close();
        }
    }

    static void run() throws MemoryReleaseError {
        try( ResourceGrabber object = new ResourceGrabber() ) {
            int i = 10 / 0;
        }
    }

    public static void main( String[] args ) {
        try {
            buggyRun();
        } catch ( Exception e ) {
            e.printStackTrace( System.out );
        }
    }
}

Program’s output should be

Let's grab some memory...
MemoryReleaseError
	at ResourceGrabber.close(ExceptionTester.java:9)
	at ExceptionTester.buggyRun(ExceptionTester.java:19)
	at ExceptionTester.main(ExceptionTester.java:31)


The ResourceGrabber object is constructed in buggyRun(). It grabs some memory. Then java.lang.ArithmeticException is generated with devision by zero, flow control goes to finally block. close() method is called in order to release grabber resources but new exception (MemoryReleaseError) is thrown. As you may see from the output, our main’s try block has caught the only exception – MemoryReleaseError. We still known nothing about ArithmeticException.

Now, lets add “true” run() method, using Java 7th try-with-resources statement:

static void run() throws MemoryReleaseError {
    try( ResourceGrabber object = new ResourceGrabber() ) {
        int i = 10 / 0;
    }
}

Also, lets update our main() in the next way:

public static void main( String[] args ) {
    try {
        buggyRun();
    } catch ( Exception e ) {
        e.printStackTrace( System.out );
    }

    System.out.println( "\n-----------\n" );

    try {
        run();
    } catch ( Exception e ) {
        e.printStackTrace( System.out );

        if( e.getSuppressed().length > 0 ) {
            System.out.println( "Suppressed exception have been found:" );
            for( Throwable suppressed : e.getSuppressed() )
                System.out.format(
                    "Suppressed exception is '%s'\n",
                    suppressed.getClass().getName()
                );
        }
    }
}

Let’s compile and run the program and see what’s happened:

Let's grab some memory...
MemoryReleaseError
at ResourceGrabber.close(ExceptionTester.java:51)
at ExceptionTester.buggyRun(ExceptionTester.java:9)
at ExceptionTester.main(ExceptionTester.java:21)

-----------

Let's grab some memory...
java.lang.ArithmeticException: / by zero
at ExceptionTester.run(ExceptionTester.java:15)
at ExceptionTester.main(ExceptionTester.java:29)
Suppressed: MemoryReleaseError
at ResourceGrabber.close(ExceptionTester.java:51)
at ExceptionTester.run(ExceptionTester.java:16)
... 1 more
Suppressed exception have been found:
Suppressed exception is 'MemoryReleaseError'

The pre-“——” part remains the same: we have performed buggyRun() and stayed in the lack of java.lang.ArithmeticException exception.

Get down to discuss run() call: method run() is performed. The ResourceGrabber object is constructed in try-with-resources statement. Then ArithmeticException is generated, and grabber’s close() method is implicitly called, which generates MemoryReleaseError exception. Flow control goes to the main() and finds itself under catch( Exception e ) statement. ‘e’ is the very first exception occurred: java.lang.ArithmeticException one. The try-with-resources has suppressed our MemoryReleaseError exception and put it into ArithmeticException!

Class Throwable got getSuppressed() method, that returns array (Throwable[]) of all suppressed exceptions so we could easy get access to each of them and miss nothing important.

The C++ doesn’t have such problems: it guarantees that terminate() will be called if any new exception is thrown while existing exception hasn’t yet reached the try-catch block. There is no finally block in C++ hence the only possibility to reproduce the situation mentioned above is to raise exception in the destructor. In most cases this is a bad idea and you should do this very carefully (as almost everything you do into destructors :)):

#include <iostream>


class VeryImportantException {};
class MyException {};

struct ExceptionTester {
	void run() {
		std::cout << "ExceptionTester::run()" << std::endl;

		std::cout << "Before throwing VeryImportantException" << std::endl;
		throw VeryImportantException();
		std::cout << "After VeryImportantException has been thrown" << std::endl;
	}

	~ExceptionTester() {
		std::cout << "~ExceptionTester" << std::endl;

		std::cout << "Before throwing MyException" << std::endl;
		throw MyException();
		std::cout << "After MyException has been thrown" << std::endl;
	}
};


int main() {
	try {
		ExceptionTester e;
		e.run();
	} catch( const MyException& e ) {
		std::cout << "MyException has been cought!" << std::endl;
	} catch( const VeryImportantException& e ) {
		std::cout << "VeryImportantException has been cought!" << std::endl;
	}

	return 0;
}

Two methods have been defined for the class ExceptionTester: run() which throws VeryImportantException and destructor which throws MyException. In main we just construct the ExceptionTester object on stack in try-catch block. If you compile and run the program above, you should get:

ExceptionTester::run()
Before throwing VeryImportantException
~ExceptionTester
Before throwing MyException
terminate called after throwing an instance of 'MyException'
Aborted

We enter the ExceptionTester::run(), then we throw VeryImportantException, then flow control goes out of scope where ExceptionTester object was defined hence ~ExceptionTester was called and just after throwing MyException we’ve got ‘terminate called after throwing an instance of ‘MyException’ and termination. That’s happened because MyException has been thrown while VeryImportantException hasn’t reached the try-catch block yet. Even with this behavior we know nothing about VeryImportantException (which was the first problem), but C++ doesn’t give us an ability just to “forget” about it and continue with program execution.

C++ behavior is the strictest one among Java and C#, and obviously isn’t a panacea: it’s nice that C++ doesn’t give us ability to lose some exception but terminate() in situation where we really may fix the problem in runtime – is not a good idea. Java 7th with its suppressed exceptions and try-with-resources statement gives us the more flexible way for solving issues mentioned above, and as a result – more benefits during design stage.

Advertisements

How to get astride a zombie.

September 15, 2011

Hello everyone!

Today I’m going to show you how to summon some zombies, how to control and get rid of them.

During the hiring process to the UNIX Perl developer position, I like to ask applicants about zombies.

Generally, there are some scrappy answers, like:

  • Zombies are bad
  • Ah… someone has died
  • Zombies always irritate someone

These rumors go rather from computer games, books and films then from UNIX internals.

Generally, only 20% of applicants could explain what zombies are, and only 5% of them could write a simple program which produces some of these funny creatures.
I think that If you are not able to summon zobies then you cann’t feel that some thirdparty code does it unless its too late.

Lets get down to business…

Zombies
Zombie (or defunct) process is a process that has completed execution but still has an entry in the process table. First confuse within such definitin is a “process” word. In fact, zombie is not a process, it’s just a shadow of an ordinary UNIX process. Zombie has already released the memory and it doesn’t use CPU time. Process which became zombie has left the only trace in the system – an entry in the system process list table. But what for? Its time to get tour into UNIX IPC…

UNIX IPC.
Every process in UNIX system should have a parent. Frankly speaking it’s not a full truth. The very first process is the kernel. It hasn’t parent. The Kernel runs init – the process which gets PID (process ID) 1 and then spawns all others processes in system. So we could rewrite first sentence in such way: every ordinary process in UNIX system should have a parent.

Each decent parent should look after its children. When the parent dies – its children are adopted and being looked after by init process. What does it mean: “to look after“? Well, in UNIX IPC it means:

  • Check for the signal that someone of process’es children has died.
  • Get children’s exit status from system.

If parent doesn’t perform either of rules above – then its children become zombie after death.
UNIX system guarantees that the init process is always keep track of its children, so, if some process appears to be a direct child of init – then it never becomes zombie.

Now, we could turn back to zombie’s definition and update it a little bit: zombie (or defunct) process is a process that has completed execution but still has an entry in the process table, because (and, in fact, until) parent process hasn’t got its exit status form system.

So, with this definition in mind, we could write a simple Perl script to summon a zombie:

#!/usr/bin/perl

use warnings;
use strict;

print "$$: Hello, I'm a parent process\n";

my $pid = fork;
die "Cann't fork: $!" unless defined $pid;

if( $pid > 0 ) {
    while( 1 ) {}
} else {
    print "\t\\_ $$: Hello, I'm a child process\n";
}

exit 0;

At first, we print hello message with parent’s PID. Then we perform fork call, and print hello message with child’s PID – if we are in child process, or perform an infinite loop – if we are in parent one.
We use infinite loop – to make our parent to be alive during the death of its child. Else, our parent will exit, its child will be reparented to the init process, and zombie will be destroyed.

Output of this program should be:

$ ./Zombie1.pl 
31604: Hello, I'm a parent process
	\_ 31605: Hello, I'm a child process

Leave this program running, and switch to another terminal. Perform a ps:

$ ps fo pid,comm
  PID COMMAND
31409 bash
32395 \_ Zombie1.pl
32396    \_ Zombie1.pl <defunct>

We have asked ps to show PID and COMMAND datas of system processes in hierarchy form (so called forest). What we can see here? There is a bash process which has PID 31409. This bash process runs another one – our Zombie1.pl program, and, at last, we get a zombie process – PID: 32396, which is a child of Zombie1.pl process. Word <defunct> shows that this process is zombie (waiting for parent to get its exit status).

Now, lets ask ps to show us more wide statistic:

$ ps fo pid,%cpu,%mem,rss,command
  PID %CPU %MEM   RSS COMMAND
31409  0.1  0.3   1816 -bash
32395 92.0  0.3   1748 \_ /usr/bin/perl ./Zombie1.pl
32396  0.0  0.0     0     \_ [Zombie1.pl] <defunct>

Here, we have asked ps to show us CPU and memory usage for each process (%cpu, %mem and rss keys). You may see that defunct process doesn’t use processor and memory of the system. It’s nothing more then just a process table record.

If we turn back to the terminal where our Zombie1.pl script is running, press Ctrl+C (i.e.: send interrupt signal to the program) then our Zombie1.pl (PID: 32395) will die, its zombie child will be taken care and destroyed by init process.

Now we will try to manage our child more carefully.
At fist we will add SIGCHLD handler:

use POSIX ":sys_wait_h";

$SIG{CHLD} = sub {
    print "$$: Has got a SIGCHLD signal\n";
    my $pid = waitpid( -1, WNOHANG );
    if( $pid > 0 ) {
        my $exit_status = $? >> 8;
        my $signal_number = $? & 127;
        my $has_dump = $? & 128;

        print "$$: Child $pid has died with exit status $exit_status.\n";

        if( $signal_number > 0 ) {
            print "$$: Child $pid was killed by signal $signal_number.\n";
        }

        if( $has_dump ) {
            print "$$: Child $pid has left core dump.\n";
        }
    }   
};

We made an anonymous handler for SIGCHLD signal. Into that handler we print a message and then performs a waitpid call.

We may translate waitpid( -1, WNOHANG ) like: Kernel! Give me information!
-1 – as a first parameter of waitpid, means “all my children”, and WNOHANG as second one – “use non-blocking wait”.
So, the whole waitpid construction may be treated like: Kernel, give me information about one of my dead children. If no such info – return immediate.

waitpid returns the pid of the deceased process, or “-1” if there is no such child process.The status is returned in $?. This status is actually two 8-bit values in one 16-bit number. The high byte – is a process exit status. Low byte describes two parameters: low 7 bits describe a signal that killed the process, and the 8th bit indicates whether a core dump occurred. Hence there is a code with some binary arithmetic.

Here is the full program listing:

#!/usr/bin/perl

use warnings;
use strict;
use POSIX ":sys_wait_h";

$SIG{CHLD} = sub {
    print "$$: Has got a SIGCHLD signal\n";
    my $pid = waitpid( -1, WNOHANG );
    if( $pid > 0 ) {
        my $exit_status = $? >> 8;
        my $signal_number = $? & 127;
        my $has_dump = $? & 128;

        print "$$: Child $pid has died with exit status $exit_status.\n";

        if( $signal_number > 0 ) {
            print "$$: Child $pid was killed by signal $signal_number.\n";
        }

        if( $has_dump ) {
            print "$$: Child $pid has left core dump.\n";
        }
    }   
};                                                                          
                                                                            
print "$$: Hello, I'm a parent process\n";                                  
                                                                            
my $pid = fork;                                                             
die "Cann't fork: $!" unless defined $pid;                                  
                                                                            
if( $pid > 0 ) {                                                            
    while( 1 ) {}                                                           
} else {                                
    print "\t\\_ $$: Hello, I'm a child process\n";
    exit 123;
}                                       
                                        
exit 0;

Pay your attention at line 36: our child process exits with defined 123 status.
Program’s output:

$ ./Zombie2.pl 
32107: Hello, I'm a parent process
       \_ 32108: Hello, I'm a child process
32107: Has got a SIGCHLD signal
32107: Child 32108 has died with exit status 123.

You may see, that our parent process (PID: 32107) has caught SIGCHLD signal, and got its exit status.
You may verify that there is no zombie process (and there are no children at all actually) for our parent process:

$ ps fo pid,comm --ppid 32107
  PID COMMAND
$ 

Above, we have asked ps to show us all processes which have parent process 32107. As you can see – there are no such ones.

Now lets make a zombie brigade. We will define a make_child subroutine which gets int param – a status for child to exit and performs a fork:

sub make_child {
    my ( $exit_status ) = shift;
    
    my $pid = fork;
    die "Cann't fork: $!" unless defined $pid;

    unless( $pid ) {
        print "\t\\_ $$: Hello, I'm a child process and I'm going to exit with $exit_status exit status\n";
        exit $exit_status;
    }
}

After fork, parent process immediate leave the subroutine, but child one – prints a debug message and terminates with defined exit status.

In main program we will make a loop from 100 to 104, and create five make_child calls (to make five children). After it we will define infinite loop for parent process:

for ( 100 ... 104 ) {
    make_child( $_ );
}

do {} while 1;

Here is output for this program:

$ ./Zombie3.pl 
32197: Hello, I'm a parent process
       \_ 32199: Hello, I'm a child process and I'm going
                 to exit with 101 exit status
       \_ 32200: Hello, I'm a child process and I'm going
                 to exit with 102 exit status
       \_ 32201: Hello, I'm a child process and I'm going
                 to exit with 103 exit status
       \_ 32198: Hello, I'm a child process and I'm going
                 to exit with 100 exit status
       \_ 32202: Hello, I'm a child process and I'm going
                 to exit with 104 exit status
32197: Has got a SIGCHLD signal
32197: Child 32198 has died with exit status 100.

So, what has happened? Our parent process has created 5 children (each with its unique exit status), but only the first child was buried correctly. The rest ones became a zombies:

$ ps fo pid,comm --ppid 32197
  PID COMMAND
32202 Zombie3.pl <defunct>
32201 Zombie3.pl <defunct>
32200 Zombie3.pl <defunct>
32199 Zombie3.pl <defunct>

Why our parent’s code didn’t keep track of all its children? The problem (or feature) is in kernel here. Kernel keeps track of processes undelivered signals using bit vector: one bit for one signal type. So, if more then one children die before you process is scheduled, you’ll get only one SIGCHLD signal!

Thats why we should rewrite our SIGCHLD handler to use loop for calling waitpid:

$SIG{CHLD} = sub {
    print "$$: Has got a SIGCHLD signal\n";
    my $pid;
    do {
        $pid = waitpid( -1, WNOHANG ); 
        if( $pid > 0 ) {
            my $exit_status = $? >> 8;
            my $signal_number = $? & 127;
            my $has_dump = $? & 128;

            print "$$: Child $pid has died with exit status $exit_status.\n";

            if( $signal_number > 0 ) {
                print "$$: Child $pid was killed by signal $signal_number.\n";
            }

            if( $has_dump eq 1 ) {
                print "$$: Child $pid has left core dump.\n";
            }
        }
    } while $pid > 0;
};

Here we use do {} while loop to call waitpid until it returns -1 (on some UNIX systems it could be 0).

Program and ps output:

$ ./Zombie4.pl 
32221: Hello, I'm a parent process
       \_ 32223: Hello, I'm a child process and I'm going
                 to exit with 101 exit status
       \_ 32224: Hello, I'm a child process and I'm going
                 to exit with 102 exit status
       \_ 32225: Hello, I'm a child process and I'm going
                 to exit with 103 exit status
       \_ 32222: Hello, I'm a child process and I'm going
                 to exit with 100 exit status
       \_ 32226: Hello, I'm a child process and I'm going
                 to exit with 104 exit status
32221: Has got a SIGCHLD signal
32221: Child 32222 has died with exit status 100.
32221: Child 32223 has died with exit status 101.
32221: Child 32224 has died with exit status 102.
32221: Child 32225 has died with exit status 103.
32221: Child 32226 has died with exit status 104.

$ ps fo pid,comm --ppid 32221
  PID COMMAND
$

Generally, if you don’t need in your children’s exit statuses (and other info which system returns into $? variable) Perl propose a simple solution:

$SIG{CHLD} = 'IGNORE';

The 'IGNORE' at first seems to be a little confusing, but anyway, this code means: let the Perl interpreter keeps track of my children’s death. So, our the very first example (Zombie1.pl) won’t produce a zombie if we put such line into code.

In general, ‘IGNORE’ means that it’s no matter for you how your children died. It may cause many unexpected results, because from now, you may not relay on returning values of functions which use fork inside itself:

#!/usr/bin/perl

use warnings;
use strict;

$SIG{CHLD} = 'IGNORE';

my $exti_status = system( "echo 1" );
print "Echo's exit status: $exti_status\n";

exit 0;

Output:

1
Echo's exit status: -1

This program prints out “-1”, even if echo exists in your system and executes correctly.
If you comment out the $SIG{CHLD} = 'IGNORE'; line, then output will be:

$ ./Zombie6.pl 
1
Echo's exit status: 0

The danger.

So, why zombies are dangerous? Several rows into the process list are not very dreadful from first point of view… Now, I’ll show you some code. Please don’t run it until you understand what is going on here:

#!/usr/bin/perl

use warnings;
use strict;

my $i = 0;
do { $i++ } while defined make_zombie();
print "$i zombies have been summoned! Now you are not able to run anything on your system!\n";
sleep 10;
exit 0;

sub make_zombie {
    my $pid = fork;
    exit if defined $pid && pid eq 0;
    return $pid;
}

So, what do we have here? We run a function make_zombie until it returns an undef value (which means that we can’t fork anything from now). Inside make_zombie we perform a fork call, exit immediately from child process and return PID of child process to the parent.

When you run this program, at first nothing has happend. Then you will see the message like:

12014 zombies have been summoned! Now you are not able to run anything on your system!

and during 10 seconds after that moment your system will not be able to run anything. You’ll get an error messages like:

fork: retry: Resource temporarily unavailable

after any you exec activity: login to system, running ls, or mc, or another program, openning new X terminal session. Anything. All daemons, that have already been run wont work correctly too (for example apache httpd or sshd servers that perform fork inside itself when the new connection come in).

So, what has happened? Our zombies have flooded the process list table, so there are no enough space to put information for the new process. If we remove sleep 10; from the code above, the only way to do something will be to kill (Ctrl+C) current program. But if we demonize it (I’ll try to write an article about UNIX daemons in future), and system will not have an open console sessions – the only way to get rid of zombies will be reboot 😦

C++: covariance in virtual functions

September 13, 2011

Some time ago I passed a Brainbench C++ test. One of the questions in quiz seemed a little bit confusing at first glance, and I gave an incorrect answer (as I understood later, after this research). The question was related to exceptions in virtual functions: what restrictions are there in C++ on redeclaration of throw construction in virtual function in derived class? I will not provide a real question text and answers variants. And despite the fact that using of exception specification considered to be deprecated in new C++ standard I just want to show the result of my research, because the problem is quite interesting and concerns base OOP principles – plymorphism and covariance.

So, what do we know about exception specification?

  • void function(); – means that function may throw any exception and may throw nothing at all.
  • void function() throw (); – means that function doesn’t throw any exception.
  • void function() throw ( Exception ); – means that function throws the only exception of Exception. If function throws exception of other class (not an ancestor of Exception one) then we will get an unexpected() handler call.

What is unusual in virtual functions? In most cases (of cause not always) the virtual function will be overriden in the derived class. Hence the exception declaration of that virtual function should not be changed or should be changed with some restrictions into the derived class.
Imagine such situation.

#include <iostream>

struct ParentException {
    const char* whoAmI() const { return "ParentException"; }
};

struct Parent {
    virtual void exceptionGenerator() throw ( ParentException ) {
        std::cout << "void Parent::exceptionGenerator()" << std::endl;
        throw ParentException();
    }

    virtual ~Parent() {}
};

int main() {
    std::cout << "Testing Parent" << std::endl;
    std::cout << "--------------" << std::endl;

    try {
        Parent p;
        p.exceptionGenerator();
    } catch ( const ParentException& exception ) {
        std::cout << "Exception has been cought!" << std::endl;
        std::cout << exception.whoAmI() << std::endl;
    }

    return 0;
}

Here we have class Parent with the only virtual method exceptionGenerator(). This method may throw (in our case always throws) an exception ParentException – casual class with class name as returning value in whoAmI() method. Into main we construct the Parent object, call exceptionGenerator() method and catch the ParentException.

The output of this program:

Testing Parent
--------------
void Parent::exceptionGenerator()
Exception has been cought!
ParentException

Everything is quite clear and nothing unusual has happened.

Now, let’s make class Child, that derives from Parent one and reimplements exceptionGenerator() method.

struct ChildWithAnyException : public Parent {
    void exceptionGenerator() {
        std::cout << "void ChildWithAnyException::exceptionGenerator()" << std::endl;
    }
};

Pay your attention: I have called child class ChildWithAnyException because we reimplement virtual function exceptionGenerator(), telling the compiler that into ChildWithAnyException this function may throw any exception and may throw nothing. If we put this code into our program we will get a compile error, like:

looser throw specifier for ‘virtual void ChildWithAnyException ::exceptionGenerator()’
overriding ‘virtual void Parent::exceptionGenerator() throw ( ParentException )’

Compiler told us that we had forgotten to specify throw in our ChildWithAnyException::exceptionGenerator(). But why? What if we really want to do so? What problems would occur if the compiler compiled our program? Suppose there is a thirdparty library that perfectly works with Parent objects. It purports that this library will work perfectly with all classes that derived from Parent one, and as a result – with our new ChildWithAnyException class. But what will happen if we throw something different then ParentException from our ChildWithAnyException::exceptionGenerator (we are able to do so, because of absence of throw specification into function declaration)? Then our perfect library wouldn’t catch this exception and become a cause of program termination. As a ChildWithAnyException class developers we know that our class in fact doesn’t generate any exception at all. So we could rename it to ChildWithoutException and declare it in this way:

struct ChildWithoutException : public Parent {
    void exceptionGenerator() throw () {
        std::cout << "void ChildWithoutException::exceptionGenerator()" << std::endl;
    }
};

Now we can put this code into our main program and add some to main() just to ensure that everything works like we expect:

int main() {
    std::cout << "Testing Parent" << std::endl;
    std::cout << "--------------" << std::endl;
    try {
        Parent p;
        p.exceptionGenerator();
    } catch ( const ParentException& exception ) {
        std::cout << "Exception has been cought!" << std::endl;
        std::cout << exception.whoAmI() << std::endl;
    }

    std::cout << std::endl;
    std::cout << "Testing ChildWithoutException" << std::endl;
    std::cout << "--------------" << std::endl;
    Parent* p = new ChildWithoutException;
    p->exceptionGenerator();
    delete p;
    return 0;
}

We didn’t try to catch any exception, because we know that exceptionGenerator() method doesn’t generate them.

The output of this program:

Testing Parent
--------------
void Parent::exceptionGenerator()
Exception has been cought!
ParentException

Testing ChildWithoutException
--------------
void ChildWithoutException::exceptionGenerator()

Now, imagine that in our derived class we really want to throw new exception in exceptionGenerator() method. Not the ParentException (because, for example, it doesn’t permit us to save some important int value). So, let’s create new exception class:

class AnotherException {
        int m_id;
    public:
        AnotherException( int id ) : m_id( id ) {}

        int getId() const { return m_id; }
        const char* whoAmI() const { return "AnotherException"; }
};

This is a quite simple class which provides ability to hold some int value.

Now, we are going to implement a new class, which derives from Parent one and throws inside its virtual exceptionGenerator() two exceptions: ParentException (as Parent class does) and the new one – AnotherException (for our new purposes):

struct ChildWithAdditionalException : public Parent {
    void exceptionGenerator() throw ( ParentException, AnotherException ) {
        std::cout << "void ChildWithAdditionalException::exceptionGenerator()" << std::endl;
        throw AnotherException( 100 );
    }
};

And again this code wont be compiled. The problem is in AnotherException – code that has already been working with class Parent knows nothing about our new AnotherException, so in case when this code will get pointer Parent* to the object ChildWithAdditionException type, an exception AnotherException wont be caught and terminate occurs.

So, what should we do in order to throw an exception from exceptionGenerator() with some new (in our case – int) params, that can’t be done with ParentException? The only way to do it is to derive new exception from ParentException:

class ChildException : public ParentException {
        int m_id;
    public:
        ChildException( int id ) : m_id( id ) {}

        int getId() const { return m_id; }
        const char* whoAmI() const { return "ChildException"; }
};

struct ChildWithDerivedException : public Parent {
    void exceptionGenerator() throw ( ChildException ) {
        std::cout << "void ChildWithDerivedException::exceptionGenerator()" << std::endl;
        throw ChildException( 100 );
    }
};

This code will be compiled. Again, the code that can work with Parent class only, knows nothing about ChildException. But catch( ParentException& ) construction (in either variasions: catch( ParentException* ), or even catch( ParentException ) ) will catch ChildException exception in any case (because ChildException is a child of ParentException).

So, the full answer for the question should be: we could redeclare throw part of virtual function definition in derived class only if

  • We declare it to throw nothing (using throw ()).
  • New exceptions are descendants of exceptions, being thrown in parent class.

Or in one sentence: it must be at least as restrictive as base throw declaration.

Also I’d like to explain “…at least as restrictive” phrase, because there were some difficulties in understanding this conception for me. Suppose we have such method in class:

virtual void function() throw ( Exception1, Exception2, Exception3 );

then, definition in the derived class (without Exception3, for example)

virtual void function() throw ( Exception1, Exception2 );

would be more restrictive then previous one. So, definition

virtual void function() throw ();

would be the most restrictive (from exception definition point of view).

Now, I’d like to describe one more example of reloading virtual functions. In that case we will talk about changing of return value type of virtual functions.

Lets use abstract factory pattern to implement process of creating music instruments.
At first we’ll create interface and classes for music instruments piano and guitar:

struct MusicInstrument {
    virtual ~MusicInstrument() {};
    virtual void play() = 0;
};

struct Piano : public MusicInstrument {
    ~Piano() { std::cout << "Piano::~Piano" << std::endl; }
    void play() { std::cout << "Piano::play" << std::endl; }
};

struct Guitar : public MusicInstrument {
    ~Guitar() { std::cout << "Guitar::~Guitar" << std::endl; }
    void play() { std::cout << "Guitar::play" << std::endl; }
};

Here we have an interface class MusicInstrument and two musical instrument’s classes which implements this interface: Guitar and Piano. Our music instruments can play using play() method (just print to the stdout). Now, we will create an interface and classes for music instrument’s factories:

struct MusicInstrumentFactory {
    virtual MusicInstrument* createInstrument() = 0;
};

struct PianoInstrumentFactory : public MusicInstrumentFactory {
    MusicInstrument* createInstrument() {
        std::cout << "PianoInstrumentFactory::createInstrument" << std::endl;
        return new Piano;
    }
};

struct GuitarInstrumentFactory : public MusicInstrumentFactory {
    MusicInstrument* createInstrument() {
        std::cout << "GuitarInstrumentFactory::createInstrument" << std::endl;
        return new Guitar;
    }
};

The MusicInstrumentFactory may manufacture a MusicInstrument using its createInstrument() method. This method is overloaded into PianoInstrumentFactory and GuitarInstrumentFactory to produce Piano and Guitar classes respectively.

Now, we can write a main code, just to ensure that factory pattern method works properly:

#include <vector>
#include <stdio.h>
#include <stdlib.h>

int main() {
    srand( time(NULL) );

    typedef std::vector<MusicInstrumentFactory*> MusicFactory;
    MusicFactory factoryVector;
    for( int i = 0; i < 5; ++i )
        if( (rand() % 10) > 5 )
            factoryVector.push_back( new PianoInstrumentFactory );
        else
            factoryVector.push_back( new GuitarInstrumentFactory );

    for( MusicFactory::iterator it = factoryVector.begin(); it != factoryVector.end(); ++it ) {
        std::cout << "----------" << std::endl;
        MusicInstrument* instrument = (*it)->createInstrument();
        instrument->play();
        delete instrument;
        delete *it;
    }
}

We create a vector of pointers to MusicInstrumentFactory. Fill it with PianoInstrumentFactory and GuitarInstrumentFactory objects using simple randomizer: so we don’t know, what factory (Piano or Guitar) is placed into particular vector’s cell. Then we iterate over the vector and call play() method for each object. C++ knows which function to call, so for Piano object program prints Piano::play string and for Guitar one – Guitar::play. The output for this program on my computer was:

----------
PianoInstrumentFactory::createInstrument
Piano::play
Piano::~Piano
----------
PianoInstrumentFactory::createInstrument
Piano::play
Piano::~Piano
----------
PianoInstrumentFactory::createInstrument
Piano::play
Piano::~Piano
----------
GuitarInstrumentFactory::createInstrument
Guitar::play
Guitar::~Guitar
----------
PianoInstrumentFactory::createInstrument
Piano::play
Piano::~Piano

It means, that during runtime, the program creates 4 Piano Factory objects and the Guitar one. So four pianos and the gruitar were manufactured.

Now, imagine, that we want to implement some non-virtual methods inside Piano class. For example, pianos have a pedal to perform the continuous sound. We’ll create a pressThePedal() method to simulate it.

Now, our Piano class should look like

struct Piano : public MusicInstrument {
    ~Piano() { std::cout << "Piano::~Piano" << std::endl; }
    void play() { std::cout << "Piano::play" << std::endl; }
    void pressThePedal() { std::cout << "Piano::pressThePedal" << std::endl; }
};

Look at the simple code fragment:

PianoInstrumentFactory pianoFactory;
MusicInstrument* piano = pianoFactory.createInstrument();
piano->play();
((Piano*) piano)->pressThePedal();
delete piano;

What’s going on here? We create a Piano Factory. Manufacture a music instrument (I have called Music Instrument’s variable piano because we know exectly what instrument could be produced by PianoInstrumentFactory class). And then we ought to cast our PianoInstrumentFactory* to Piano* in order to be able to call pressThePedal() method.

To get rid of ugly type casting we could reload the createInstrument() into PianoInstrumentFactory class to return Piano* instead of MusicInstrument*:

struct PianoInstrumentFactory : public MusicInstrumentFactory {
    Piano* createInstrument() {
        std::cout << "PianoInstrumentFactory::createInstrument" << std::endl;
        return new Piano;
    }
};

Now, the last sample code could be reweritten without casts:

PianoInstrumentFactory pianoFactory;
Piano* piano = pianoFactory.createInstrument();
piano->play();
piano->pressThePedal();
delete piano;

But, don’t forget, that when we are working with pure MusicInstrumentFactory*, we’ll get MusicInstrument* after calling createInstrument() method (not Piano* as you should imagine):

PianoInstrumentFactory* pianoFactory = new PianoInstrumentFactory;
MusicInstrument* piano = pianoFactory->createInstrument();
// Not!!!: Piano* piano = pianoFactory->createInstrument();
// error: invalid conversion from ‘MusicInstrument*’ to ‘Piano*’
piano->play();
delete piano;
delete pianoFactory;