【问题标题】:Detect usage of macro? (errno)检测宏的使用? (错误)
【发布时间】:2009-08-28 14:03:28
【问题描述】:

这是非常具体的,有点难以解释,而且很可能是不可能的,但这里就是这样。

我想实现 。 (我的爱好项目是实现一个标准 C 库。)

天真的方法是:

// in <errno.h>
extern int errno;

// in some .c file
int errno = 0;

这行得通。但它有一个缺点:如果调用数学库函数,它总是必须在执行后查询 FPU 状态以适当地设置errno。这会使 FPU 在数学繁重的应用程序中停滞不前。

C 标准通过将 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() 函数的工作方式不同,具体取决于它们是用于赋值运算符的左侧还是右侧) ,并且几乎满足于接受这一点。

但也许你们中的任何人都有一个绝妙的主意?

【问题讨论】:

    标签: c macros c-preprocessor


    【解决方案1】:

    这里没有什么绝妙的想法,但是允许通过函数调用实现 afaik errno,从而使标准库的线程安全实现成为可能。我认为懒惰地查询 FPU 不是一个好主意:在这种情况下如何避免不一致:

    • 设置errno
    • 设置错误标志的浮点操作
    • 获取errno
    • 获取标志

    是否应该致电__errno() 清除标记?

    根据标准,errno是否必须由数学函数设置由math_errhandling的值决定(具体为math_errhandling &amp; MATH_ERRNO)。

    我要做的是通过预处理器指令使错误报告成为可选,并允许程序员在编译时设置math_errhandling 的值。这意味着数学函数不能预先静态编译,而必须驻留在头文件中,无论如何,这可能是一个好主意,允许没有链接时优化的编译器内联这些函数。

    【讨论】:

      【解决方案2】:

      你在这里得到的是一个很好的分析,为什么整个errno 机制如此不令人满意。您也可以在 Kernighan 的“标准 C 库”中找到类似的分析。

      线程安全实现也需要errno 的函数形式,其中不同的线程具有通过线程特定的errno 访问的单独错误值。

      为了安全起见,您的宏可能应该有括号:

      #define errno (*__errno())
      

      【讨论】:

        【解决方案3】:

        更多的是评论而不是答案,但如果没有代码格式化,它将无法理解。

        如果你懒惰地检查 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 */
        }
        

        【讨论】:

          猜你喜欢
          • 2021-08-25
          • 1970-01-01
          • 1970-01-01
          • 2012-02-15
          • 2014-11-26
          • 2018-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多