GNU Octave: Exception and Error Handling in Oct-Files

Next: Documentation and Test of Oct-Files, Previous: Input Parameter Checking in Oct-Files, Up: Oct-Files [Contents][Index]

#### 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` even during calculations. This ability is based on the C++ exception handler, where memory allocated by the C++ new/delete methods are automatically released when the exception is treated. When writing an oct-file, to allow Octave to treat the user typing `Control-C`, the `OCTAVE_QUIT` macro is supplied. 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 treat the user request with the `Control-C`. Without this macro, the user must either wait for the function to return before the interrupt is processed, or press `Control-C` three times to force Octave to exit.

The `OCTAVE_QUIT` macro does impose a very small speed penalty, and so for loops that are known to be small it might not make sense to include `OCTAVE_QUIT`.

When creating an oct-file that uses an external libraries, 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 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 is important to enforce that certain code is run to allow variables, etc. to be restored 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!!
    }

    DEFUN_DLD (unwinddemo, args, nargout, "Unwind Demo")
    {
      octave_value retval;
      int nargin = args.length ();

      if (nargin < 2)
        print_usage ();
      else
        {
          NDArray a = args(0).array_value ();
          NDArray b = args(1).array_value ();

          if (! error_state)
            {
              // Declare unwind_protect frame which lasts as long as
              // the variable frame has scope.
              unwind_protect frame;
              frame.protect_var (current_liboctave_warning_handler);

              set_liboctave_warning_handler (my_err_handler);
              retval = octave_value (quotient (a, b));
            }
        }
      return retval;
    }

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.

Next: Documentation and Test of Oct-Files, Previous: Input Parameter Checking in Oct-Files, Up: Oct-Files [Contents][Index]