Octave的另一个重要特性是其能够在长时间计算过程中响应用户键入的
Control-C。该能力基于C++异常处理机制,当异常被处理时,由C++ new/delete方法分配的内存会被自动释放。在编写可能长时间运行的oct-file时,程序员必须定期使用宏
OCTAVE_QUIT,以允许Octave检查并可能响应用户键入的Control-C。例如:
for (octave_idx_type i = 0; i < a.nelem (); i++)
{
OCTAVE_QUIT;
b.elem (i) = 2. * a.elem (i);
}
在内层循环中使用OCTAVE_QUIT 宏,使得Octave能够检测并响应Control-C按键序列。如果没有这个宏,用户必须等待oct-file函数返回后中断才会被处理,或者用户必须连续按三次Control-C,这会强制Octave完全退出。
OCTAVE_QUIT 宏确实会带来非常小的性能开销;
对于已知循环次数很少的情况,使用OCTAVE_QUIT可能没有意义。
当创建使用外部库的oct-file时,函数可能会在外部库中花费大量时间。在这种情况下,通常无法使用OCTAVE_QUIT 宏。针对此情况的替代代码如下:
BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; ... 一些调用"外部"函数的代码 ... END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
这样做的缺点是,如果外部代码在内部分配了任何内存,那么这些内存可能会在中断期间丢失而无法被释放。因此,理想情况下,Octave本身应使用rwdata方法或OCTAVE_LOCAL_BUFFER 宏来分配外部代码所需的所有内存。
Octave的unwind_protect机制
(参见unwind_protect 语句)也可以用在oct-file中。它与Octave的异常处理机制相结合,确保即使在发生异常时,某些恢复代码也始终会被执行。以下是一个使用此机制的示例:
#include <octave/oct.h>
#include <octave/unwind-prot.h>
void
my_err_handler (const char *fmt, ...)
{
// 什么都不做!!
}
void
my_err_with_id_handler (const char *id, const char *fmt, ...)
{
// 什么都不做!!
}
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 ();
// 创建 unwind_action 对象。在封闭作用域结束时,
// 这些对象的析构函数将使用指定的参数调用给定的函数。
octave::unwind_action restore_warning_handler
(set_liboctave_warning_handler, current_liboctave_warning_handler);
octave::unwind_action restore_warning_with_id_handler
(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));
}
从示例中可以看出:
unwinddemo (1, 0) ⇒ Inf 1 / 0 ⇒ warning: division by zero Inf
在unwinddemo函数中,除零警告(实际上包括所有警告)都被禁用了。
版权所有 © 2024-2026 Octave中文网
ICP备案/许可证号:黑ICP备2024030411号-4