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/。

