检测宏的使用? (错误号)
这是非常具体的,有点难以解释,而且很可能是不可能的,但就是这样。
我想实现
简单的方法是:
// 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()
函数以某种方式工作,具体取决于它们是用于赋值运算符的左侧还是右侧),我几乎满足于接受这一点。
但也许你们中的任何一个 SO'ers 有一个绝妙的主意?
This is very specific, and a bit difficult to explain, and quite likely impossible, but here goes.
I want to implement <errno.h>. (My hobby project is implementing a Standard C library.)
The naïve way to go about it is:
// in <errno.h>
extern int errno;
// in some .c file
int errno = 0;
This works. But it has one disadvantage: If a math library function is called, it always has to query the FPU status after execution to set errno
as appropriate. This stalls the FPU in math-heavy applications.
The C standard endorses lazy evaluation of errno
by making it a macro instead:
int * __errno();
#define errno *__errno()
This way, errno
is only "set" when its value is actually requested:
// "__errno()" returns the location of the current errno value,
// the "errno" macro turns it into a value.
x = errno;
Given some logic in the rest of the library, the FPU status needs only be queried if the last library function called was actually one using the FPU, and the value of errno
is actually requested.
So far, everything is fine. But it's the other way around that is giving me headaches:
errno = 0;
The value of errno
is not requested at all. But __errno()
does not know that, and will query the FPU status if the last library function called was using the FPU.
Right now I don't see a way to avoid that (i.e., have the errno
macro or the __errno()
function somehow work differently depending on whether they are used to the left or the right of the assignment operator), and am almost content to accept this.
But perhaps any of you SO'ers has a brilliant idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里没有什么绝妙的想法,但是 afaik errno 可以通过函数调用来实现,以使标准库的线程安全实现成为可能。我不认为延迟查询 FPU 是一个好主意:如何避免在这种情况下出现不一致:
errno
errno
调用 __errno() 是否应该清除标志?
根据标准,数学函数是否必须设置
errno
由math_errhandling
的值决定(具体来说,math_errhandling & MATH_ERRNO
)。我要做的是通过预处理器指令使错误报告成为可选,并允许程序员在编译时设置 math_errhandling 的值。这意味着数学函数不能预先静态编译,而必须驻留在标头中,无论如何,这可能是一个好主意,允许没有链接时优化的编译器内联这些函数。
No brilliant ideas here, but afaik
errno
is allowed to be implemented via function calls to make thread-safe implementations of the standard library possible. I don't think querying the FPU lazily is a good idea: How will you avoid inconsistency in situations like this:errno
errno
Should a call to
__errno()
clear the flags or not?According to the standard, whether or not
errno
has to be set by math functions is determined by the value ofmath_errhandling
(specifically,math_errhandling & MATH_ERRNO
).What I would do is make the error reporting optional via preprocessor directives and allow the programmer to set the value of
math_errhandling
at compile time. This would mean that the math functions can't be compiled statically beforehand but have to reside in a header, which might be a good idea anyway to allow compilers without link-time optimizations to inline these functions.这里对为什么整个 errno 机制如此不令人满意进行了相当好的分析。您也可以在 Kernighan 的“标准 C 库”中找到类似的分析。
线程安全实现也需要 errno 的函数形式,其中不同的线程具有通过特定于线程的 errno 访问的单独错误值。
为了安全起见,你的宏应该有括号:
What you have here is a fairly good analysis of why the whole
errno
mechanism is so unsatisfactory. You could find a similar analysis in Kernighan's "The Standard C Library" too.The functional form of
errno
is also needed for thread-safe implementations, where different threads have separate error values accessed via a thread-specificerrno
.Your macro should probably have parentheses around it for safety:
更多的是评论而不是答案,但是如果没有代码格式化,它将无法理解。
如果您懒惰地检查 FPU 标志,那么这里的行为如何正确(数学函数很特殊,因为它们保证在没有问题时不会修改 errno)?
More a comment than an answer, but without code formatting it would not be understandable.
If you check lazily the FPU flags, how would you have the correct behavior here (the math functions are special in that they are guaranteed not to modify errno when there is no problem)?