浮点和整数算术运算可能会导致异常,例如溢出和被零除。此类异常通常无提示,因此系统会返回合理答案(例如 NaN)作为导致异常的运算的结果。因此,这些异常对 dbx 不可见。
您可以进行设置使得出现异常时不再无提示,而是导致陷阱。然后,操作系统将陷阱转换为 SIGFPE 并将其传送到进程,dbx 可以拦截此信号传送。请注意以下几点:
缺省情况下,F77 不会在出现任何浮点异常时自陷。
缺省情况下,F95 会在出现无效操作数、除以零和溢出异常时自陷,但不会在出现下溢和不精确异常时自陷。
缺省情况下,C 和 C++ 不会在出现浮点异常时自陷。
没有针对整数溢出进行置备以隐式触发 SIGFPE。在 SPARC 上,您可以使用 TVS (trap-on-overflow-set) 汇编指令。在 SPARC 或 Intel 上,您可以使用类似 branch-on-overflow-set 的指令。
要查找导致异常的原因,需要在程序内设置陷阱处理程序,以使异常触发 SIGFPE 信号。
可使用下列方式启用陷阱:
fpsetmask-此函数严格控制陷阱的启用。请参见 fpsetmask(3C) 手册页。
示例:
#include <ieeefp.h> int main() { fpsetmask(FP_X_INV|FP_X_OFL|FP_X_UFL|FP_X_DZ|FP_X_IMP); ...
ieee_handler-不存在 Fortran 的 psetmask(3c) 精确模拟。相反,您可通过按如下所有建立缺省行为,以启用陷阱。
示例:
integer*4 ieeer ieeeer = ieee_handler('set', 'common', SIGFPE_DEFAULT)
有关更多信息,请参见 ieee_environment(3f) 和 ieee_handler(3m) 手册页。
-ftrap 编译器标志-此标记类似于 fpsetmask()(),它将严格控制陷阱的启用。有关 Fortran 95 的信息,请参见 f95(1) 手册页。
使用以上方法之一启用浮点陷阱时,系统将设置硬件浮点状态寄存器中的陷阱启用掩码。此陷阱启用掩码会导致异常在运行时引发 SIGFPE 信号。
插入对 fpsetmask()() 或 ieee_handler()() 的调用,或使用陷阱处理程序编译程序后,将程序装入到 dbx 中。从 Oracle Solaris Studio 12.4 起,SIGFPE 在缺省情况下已捕获。使用旧版本的 dbx 时,请确保该信号仍在捕获列表中。
(dbx) catch FPE
您可以通过对 fpsetmask() 和 ieee_handler() 的参数稍作调整,并通过使用 dbx 捕获命令的替代命令,就如捕获 FPE 一样,进一步量身定制查看哪些特定异常。
(dbx) stop sig FPE (dbx) ignore SIGFPE #don't catch it twice
可以使用以下代码优化控制:
stop sig FPE subcode
其中 subcode 可以是下列选项之一:
整数除以零。
整数溢出。
浮点除以零。
浮点溢出。
浮点下溢。
浮点不精确结果。
无效的浮点运算。
下标超出范围。
将 FPE 添加到捕获列表后,在 dbx 中运行程序。出现要捕获的异常时,系统将引发 SIGFPE 信号且 dbx 会停止程序。然后,可以使用 dbx where 命令跟踪调用堆栈,以帮助查找程序中发生该异常的特定行号。
要确定导致 SPARC 异常的原因,请使用 regs -f 命令显示浮点状态寄存器 (floating point state register, FSR)。 查看寄存器的已产生的异常 (aexc) 和当前异常 (cexc) 字段,这些字段包含下列浮点异常条件位:
无效操作数
溢出
下溢
除以零
不精确结果
在 Intel 中,x87 的浮点状态寄存器是 fstat,SSE 的浮点状态寄存器是 mxcsr。
有关浮点状态寄存器的更多信息,请参见《The SPARC Architecture Manual》的版本 8 (V8) 或版本 9 (V9)。有关更多讨论和示例,请参见Oracle Solaris Studio 12.4:数值计算指南 。