代码之家  ›  专栏  ›  技术社区  ›  Robert S. Barnes Antoni

如何获得posix strerror_r而不是gnu版本?

  •  9
  • Robert S. Barnes Antoni  · 技术社区  · 14 年前

    我怎么弄到POSIX strerror_r 而不是GNU版本?

    我正在使用g++在Ubuntu8.04上使用glibc 2.7版(基于中的内容)进行编译。

    编辑

    在上面的手册页上写着:

    glibc的功能测试宏要求(参见功能测试宏(7)):

       The XSI-compliant version of strerror_r() is provided if:
       (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
       Otherwise, the GNU-specific version is provided.
    

    然后说 feature_test_macros(7) :

       If no feature test macros are explicitly defined, then the following feature
       test macros are defined by default: _BSD_SOURCE, _SVID_SOURCE, _POSIX_SOURCE,
       and _POSIX_C_SOURCE=200809L (200112L in glibc versions before 2.10; 199506L in
       glibc versions before 2.4; 199309L in glibc versions before 2.1).
    

    所以我应该得到posix版本,但我得到的是gnu版本。

    3 回复  |  直到 10 年前
        1
  •  7
  •   Tim Post Samir J M Araujo    12 年前

    从页眉 string.h :

    /* Reentrant version of `strerror'.
       There are 2 flavors of `strerror_r', GNU which returns the string
       and may or may not use the supplied temporary buffer and POSIX one
       which fills the string into the buffer.
       To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L
       without -D_GNU_SOURCE is needed, otherwise the GNU version is
       preferred.  */
    

    注意,使用GNU扩展时要小心,打开它们。( _GNU_SOURCE )最后,在包含您希望它影响的标题之前(或从策略上取消定义它)。不过,如果不使用GNU扩展,则无需担心。

    通常,如果GNU在默认行为中偏离了POSIX,您将在头部看到一些注释,以指示如何获得POSIX行为。它也(通常)记录在glibc手册中,但这并不总是使它进入高度浓缩的手册页。

    编辑

    尝试这个简单的测试:

    #include <string.h>
    #ifdef _GNU_SOURCE
    #error "Something turned it on!"
    #endif
    

    或者更直接地说

    #ifdef _GNU_SOURCE
    #undef _GNU_SOURCE
    #endif
    #include <string.h>
    

    如果 _POSIX_C_SOURCE={version} 定义,你 应该 使用POSIX版本,除非其他原因导致更喜欢GNU版本。

    我唯一能想到的就是 γ源 . 我敢肯定这不在你的命令行标志上,你会看到的。可能是包含的另一个库打开了它。

    这就是我的意思,当请求支持POSIX实现时,扩展是“棘手的”,即使您不是开启它们的人。

    编辑

    如果有什么东西打开了 γ源 (我不记得Boost是否执行,我不使用C++几乎和C一样多),你可能想允许它这样做。你可以使用 --undef "[macro]" -U[macro] 从命令行。但是,如果库代码如下所示,则这不起作用:

    #ifndef _GNU_SOURCE
    #define _GNU_SOURCE
    #endif
    
    #include <stdio.h>
    #include <string.h>
    
    #ifdef _GNU_SOURCE
    #error "It didn't work"
    #endif
    
    int main(void)
    {
       return 0;
    }
    

    问题是,当您的代码实际包含 字符串 ,其他一些已打开扩展并包含它。包括警卫自然会阻止你包括它两次。

    尝试显式关闭 γ源 并且包括 字符串 之前 任何东西 否则。这会阻止其他库打开这些扩展。但是,没有它们,这些库可能无法工作。有些代码只是“期望”GNU行为,不包括对POSIX的回退。

    我也曾遇到过类似的挫折,因为库代码没有 asprintf() .

        2
  •  2
  •   R.. GitHub STOP HELPING ICE    14 年前

    虽然标准中不要求线程安全,但我无法想象一个理智的人可以用什么方法编写一个非线程安全的 strerror . 人们做什么, gunzip 运行时的错误字符串还是什么?好! 斯特朗 应返回指向标准库中字符串常量或常量的指针 mmap 'd来自区域设置消息文件的内存。

    很抱歉,这不是一个真正的答案,但是如果您不关心绝对理论上的可移植性,您可能会检查并查看您关心的所有实现是否都正常。 斯特朗 行为,如果是的话,就用它来代替。

        3
  •  1
  •   user877329    10 年前

    这是一个特定于实现的解决方案。

    #ifdef __cplusplus
    extern "C"
        {
    #endif
        extern 
        int __xpg_strerror_r(int errcode,char* buffer,size_t length);
        #define strerror_r __xpg_strerror_r
    
    #ifdef __cplusplus
        }
    #endif