In C++ FAQ, the [16.16] gives the following example,
void manipulateArray(unsigned nrows, unsigned ncols[])
{
typedef Fred* FredPtr;
FredPtr* matrix = new
The try/catch block is necessary to ensure proper clean-up even if an exception is thrown anywhere in the code before the normal clean-up happens. This includes an exception in one of the new expressions. The delete[] is safe because all the relevant pointers were initially set to zero, so that the deletion is valid even if no allocation ever occurred.
(Note that if any exception does occur, it will still be propagated outside the function. The local try/catch block only ensures that the function itself doesn't leak any memory.)
There are two sets of arrays: one is the outer array matrix, which is an array of pointers. This array gets allocated first and deleted last. Second, each element matrix[i] is itself a pointer to an array of Fred elements. Each array gets allocated in the first for loop, and thus has to be deleted in another loop at the end.