这是非常具体的,有点难以解释,而且很可能是不可能的,但如下所示。
我想实现。(我的业余项目是实现一个标准C库。)
要做到这一点,最幼稚的方法是:
// in <errno.h>
extern int errno;
// in some .c file
int errno = 0;这个很管用。但是它有一个缺点:如果调用了一个数学库函数,那么它总是必须在执行后查询FPU状态,以便适当地设置errno。这阻碍了FPU在数学方面的应用.
C标准通过将errno改为宏来认可对errno的懒惰评估:
int * __errno();
#define errno *__errno()这样,只有当errno的值被实际请求时,它才会被“设置”:
// "__errno()" returns the location of the current errno value,
// the "errno" macro turns it into a value.
x = errno;给定库的其他部分中的一些逻辑,只有当最后调用的库函数实际上是使用FPU的函数并且实际请求errno的值时,才需要查询FPU状态。
到目前为止一切都很好。但反过来让我头疼的是:
errno = 0;根本不请求errno的值。但是__errno()不知道这一点,如果最后调用的库函数是使用FPU,则会查询FPU状态。
现在,我没有办法避免这种情况(例如,让errno宏或__errno()函数以不同的方式工作,这取决于它们是习惯于赋值操作符的左边还是右边),并且几乎满足于接受这一点。
但也许你们中的任何一个人有一个绝妙的主意?
发布于 2009-08-28 15:10:54
这里没有绝妙的想法,但是允许通过函数调用实现afaik errno,从而使标准库的线程安全实现成为可能。我不认为懒洋洋地查询FPU是个好主意:在这种情况下,如何避免不一致:
设置errno
errno
对__errno()的调用是否应该清除标志?
根据标准,errno是否必须由数学函数来设置取决于math_errhandling的值(特别是math_errhandling & MATH_ERRNO)。
我要做的是通过预处理指令使错误报告成为可选的,并允许程序员在编译时设置math_errhandling的值。这意味着数学函数不能预先静态编译,而必须驻留在头中,这可能是一个好主意,因为它允许没有链接时间优化的编译器内联这些函数。
发布于 2009-08-28 15:23:02
这里所做的是对为什么整个errno机制如此不能令人满意的相当好的分析。您也可以在Kernighan的“标准C库”中找到类似的分析。
errno的功能形式也是线程安全实现所需要的,其中不同的线程通过特定于线程的errno访问不同的错误值。
为了安全起见,宏可能应该在它周围加上括号:
#define errno (*__errno())发布于 2009-08-28 18:25:33
与其说是回答,不如说是评论,但如果没有代码格式,这将是不可理解的。
如果您懒洋洋地检查FPU标志,您如何在这里有正确的行为(数学函数是特殊的,因为它们保证在没有问题时不会修改errno )?
errno = 0;
x = acos(y);
z = <exp>;
if (errno != 0) {
/* can't come here even if y is a valid argument but <exp> modified the flags if it didn't call any functions */
}https://stackoverflow.com/questions/1347208
复制相似问题