A.1.12 Exception and Error Handling in Oct-Files

Another important feature of Octave is its ability to react to the user typing Control-C during extended calculations. This ability is based on the C++ exception handler, where memory allocated by the C++ new/delete methods is automatically released when the exception is treated. When writing an oct-file which may run for a long time the programmer must periodically use the macro OCTAVE_QUIT, in order to allow Octave to check and possibly respond to a user typing Control-C. For example:

for (octave_idx_type i = 0; i < a.nelem (); i++)
  {
    OCTAVE_QUIT;
    b.elem (i) = 2. * a.elem (i);
  }

The presence of the OCTAVE_QUIT macro in the inner loop allows Octave to detect and acknowledge a Control-C key sequence. Without this macro, the user must either wait for the oct-file function to return before the interrupt is processed, or the user must press Control-C three times which will force Octave to exit completely.

The OCTAVE_QUIT macro does impose a very small performance penalty; For loops that are known to be small it may not make sense to include OCTAVE_QUIT.

When creating an oct-file that uses an external library, the function might spend a significant portion of its time in the external library. It is not generally possible to use the OCTAVE_QUIT macro in this case. The alternative code in this case is

BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
…  some code that calls a "foreign" function …
END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;

The disadvantage of this is that if the foreign code allocates any memory internally, then this memory might be lost during an interrupt, without being deallocated. Therefore, ideally Octave itself should allocate any memory that is needed by the foreign code, with either the fortran_vec method or the OCTAVE_LOCAL_BUFFER macro.

The Octave unwind_protect mechanism (The unwind_protect Statement) can also be used in oct-files. In conjunction with the exception handling of Octave, it ensures that certain recovery code is always run even if an exception occurs. An example of the use of this mechanism is

#include <octave/oct.h>
#include <octave/unwind-prot.h>

void
my_err_handler (const char *fmt, ...)
{
  // Do nothing!!
}

void
my_err_with_id_handler (const char *id, const char *fmt, ...)
{
  // Do nothing!!
}

DEFUN_DLD (unwinddemo, args, nargout, "Unwind Demo")
{
  if (args.length () < 2)
    print_usage ();

  NDArray a = args(0).array_value ();
  NDArray b = args(1).array_value ();

  // Declare unwind_protect frame which lasts as long as
  // the variable frame has scope.
  octave::unwind_protect frame;
  frame.add_fcn (set_liboctave_warning_handler,
                 current_liboctave_warning_handler);

  frame.add_fcn (set_liboctave_warning_with_id_handler,
                 current_liboctave_warning_with_id_handler);

  set_liboctave_warning_handler (my_err_handler);
  set_liboctave_warning_with_id_handler (my_err_with_id_handler);

  return octave_value (quotient (a, b));
}

As can be seen in the example:

unwinddemo (1, 0)
⇒ Inf
1 / 0
⇒ warning: division by zero
   Inf

The warning for division by zero (and in fact all warnings) are disabled in the unwinddemo function.

© 1996–2020 John W. Eaton
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://octave.org/doc/v6.3.0/Exception-and-Error-Handling-in-Oct_002dFiles.html