MATHERR - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-06-09
名称
matherr-SVID数学库异常处理
语法
#include <math.h> int matherr(struct exception *exc); extern _LIB_VERSION_TYPE _LIB_VERSION;
与-lm链接。
说明
注意:glibc不再支持此页面中描述的机制。在glibc 2.27之前,它已被标记为过时。从glibc 2.27开始,该机制已完全删除。新应用程序应使用math_error(7)和fenv(3)中描述的技术。此页面记录了matherr()机制,以帮助维护和移植较旧的应用程序。
系统V接口定义(SVID)指定如果检测到数学异常,则各种数学函数应调用一个名为matherr()的函数。在数学函数返回之前,将调用此函数;在matherr()返回之后,系统然后返回到math函数,后者又返回到调用者。
要使用matherr(),程序员必须定义_SVID_SOURCE功能测试宏(在包含任何头文件之前),并将值_SVID_分配给外部变量_LIB_VERSION。
系统提供默认版本的matherr()。此版本不执行任何操作,并返回零(有关其重要性,请参见下文)。可以由程序员定义的版本覆盖默认的matherr(),当发生异常时将调用该版本。该函数使用一个参数(指向异常结构的指针)调用,该参数的定义如下:
struct exception { int type; /* Exception type */ char *name; /* Name of function causing exception */ double arg1; /* 1st argument to function */ double arg2; /* 2nd argument to function */ double retval; /* Function return value */ }
类型字段具有以下值之一:
- DOMAIN
- 发生域错误(函数参数超出了定义函数的范围)。返回值取决于函数。 errno设置为EDOM。
- SING
- 发生极点错误(函数结果为无穷大)。在大多数情况下,返回值是HUGE(最大的单精度浮点数),并带有适当的符号。在大多数情况下,errno设置为EDOM。
- OVERFLOW
- 发生溢出。在大多数情况下,将返回值HUGE,并将errno设置为ERANGE。
- UNDERFLOW
- 发生下溢。返回0.0,并将errno设置为ERANGE。
- TLOSS
- 完全失去意义。返回0.0,并将errno设置为ERANGE。
- PLOSS
- 部分失去意义。在glibc(和许多其他系统)上未使用此值。
arg1和arg2字段是提供给函数的参数(对于仅接受一个参数的函数,arg2是未定义的)。
retval字段指定数学函数将返回给其调用方的返回值。程序员定义的matherr()可以修改此字段以更改math函数的返回值。
如果matherr()函数返回零,则系统如上所述设置errno,并可能在标准错误上显示错误消息(请参见下文)。
如果matherr()函数返回非零值,则系统不会设置errno,也不会显示错误消息。
Math functions that employ matherr()
下表列出了调用matherr()的函数和环境。 "类型"列表示调用matherr()时分配给exc-> type的值。 "结果"列是分配给exc-> retval的默认返回值。
"消息"? " errno"和" errno"列描述了matherr()返回零时的默认行为。如果是"留言"?列包含" y",然后系统在标准错误上显示错误消息。
该表使用以下符号和缩写:
x first argument to function y second argument to function fin finite value for argument neg negative value for argument int integral value for argument o/f result overflowed u/f result underflowed |x| absolute value of x X_TLOSS is a constant defined in <math.h>
示例
该示例程序演示了在调用log(3)时使用matherr()的方法。该程序最多包含三个命令行参数。第一个参数是要赋予log(3)的浮点数。如果提供了可选的第二个参数,则将_LIB_VERSION设置为SVID,以便调用matherr(),并将命令行参数中提供的整数用作matherr()的返回值。如果提供了可选的第三个命令行参数,则它指定了matherr()应该分配为数学函数的返回值的替代返回值。
以下示例运行不使用matherr(),其中log(3)的参数设置为0.0,
$ ./a.out 0.0 errno: Numerical result out of range x=-inf
在以下运行中,将调用matherr()并返回0:
$ ./a.out 0.0 0 matherr SING exception in log() function args: 0.000000, 0.000000 retval: -340282346638528859811704183484516925440.000000 log: SING error errno: Numerical argument out of domain x=-340282346638528859811704183484516925440.000000
消息"日志:SING错误"由C库打印。
在以下运行中,调用matherr()并返回非零值:
$ ./a.out 0.0 1 matherr SING exception in log() function args: 0.000000, 0.000000 retval: -340282346638528859811704183484516925440.000000 x=-340282346638528859811704183484516925440.000000
在这种情况下,C库未打印消息,并且未设置errno。
在以下运行中,将调用matherr(),更改math函数的返回值,并返回非零值:
$ ./a.out 0.0 1 12345.0 matherr SING exception in log() function args: 0.000000, 0.000000 retval: -340282346638528859811704183484516925440.000000 x=12345.000000
Program source
#define _SVID_SOURCE #include <errno.h> #include <math.h> #include <stdio.h> #include <stdlib.h> static int matherr_ret = 0; /* Value that matherr() should return */ static int change_retval = 0; /* Should matherr() change functionaqs return value? */ static double new_retval; /* New function return value */ int matherr(struct exception *exc) { fprintf(stderr, "matherr %s exception in %s() function\n", (exc->type == DOMAIN) ? "DOMAIN" : (exc->type == OVERFLOW) ? "OVERFLOW" : (exc->type == UNDERFLOW) ? "UNDERFLOW" : (exc->type == SING) ? "SING" : (exc->type == TLOSS) ? "TLOSS" : (exc->type == PLOSS) ? "PLOSS" : "???", exc->name); fprintf(stderr, " args: %f, %f\n", exc->arg1, exc->arg2); fprintf(stderr, " retval: %f\n", exc->retval); if (change_retval) exc->retval = new_retval; return matherr_ret; } int main(int argc, char *argv[]) { double x; if (argc < 2) { fprintf(stderr, "Usage: %s <argval>" " [<matherr-ret> [<new-func-retval>]]\n", argv[0]); exit(EXIT_FAILURE); } if (argc > 2) { _LIB_VERSION = _SVID_; matherr_ret = atoi(argv[2]); } if (argc > 3) { change_retval = 1; new_retval = atof(argv[3]); } x = log(atof(argv[1])); if (errno != 0) perror("errno"); printf("x=%f\n", x); exit(EXIT_SUCCESS); }
另外参见
fenv(3),math_error(7),standards(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。