Ubuntu 如何获得POSIX strerror\u r而不是GNU版本?

Ubuntu 如何获得POSIX strerror\u r而不是GNU版本?,ubuntu,g++,posix,glibc,Ubuntu,G++,Posix,Glibc,如何获得POSIX而不是GNU版本 我在Ubuntu 8.04上使用g++编译,使用的是glibc版本2.7(基于中的内容) 编辑 在上面的手册页上,它说: glibc的功能测试宏要求(参见功能测试宏(7)): 然后它在书中写道: 所以我应该得到POSIX版本,但我得到的是GNU版本。从标题string.h: /* Reentrant version of `strerror'. There are 2 flavors of `strerror_r', GNU which returns

如何获得POSIX而不是GNU版本

我在Ubuntu 8.04上使用g++编译,使用的是glibc版本2.7(基于中的内容)

编辑

在上面的手册页上,它说:

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

然后它在书中写道:


所以我应该得到POSIX版本,但我得到的是GNU版本。

从标题
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扩展时要小心,最后打开它们(
\u GNU\u SOURCE
),然后再包括您希望它影响的标题(或从策略上取消定义)。不过,如果不使用GNU扩展,则无需担心

通常,如果GNU在默认行为中与POSIX不同,您将在标题中看到一些注释,以指示如何获得POSIX行为。它也(通常)记录在glibc手册中,但这并不总是包含在高度浓缩的手册页中

编辑

尝试以下简单测试:

#include <string.h>
#ifdef _GNU_SOURCE
#error "Something turned it on!"
#endif
问题是,当您的代码实际包含
string.h
时,其他东西已经打开了扩展并包含了它。包含防护装置自然会防止您将其包含两次

尝试显式关闭
\u GNU\u SOURCE
,并在其他任何操作之前包括
string.h
。这会阻止其他库打开这些扩展。但是,如果没有它们,这些库可能无法工作。有些代码只是“期望”GNU行为,不包括POSIX的回退


对于没有asprintf()

就不能工作的库代码,我也经历过类似的挫折。虽然标准并不要求它是线程安全的,但我无法想象一个理智的人能以任何方式编写一个非线程安全的
strerror
。人们是怎么做的,
gunzip
运行时的错误字符串还是什么?!一个好的
strerror
应该返回一个指针,指向标准库中的字符串常量,或者指向区域设置消息文件中的常量
mmap
'd内存


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

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

#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

我不明白的是,文档中说默认情况下定义了
\u POSIX\u C_SOURCE=200112L
,所以我不明白为什么要得到GNU版本。我尝试了第一个版本,显然是有什么东西打开了它。我的代码中没有任何东西打开它,所以我认为它一定是来自glibc、stdlib++(STL)或Boost。有没有一种方法可以从命令行全局取消定义它?我运行了一个测试,在测试中,我选中了
\u GNU\u SOURCE
作为文件中的第一条语句,显然它是默认由g++定义的。问题是,是否将它从命令行break stuff关闭…。@RobertS.Branes为我打开breaks libstdc++.g++unded默认打开
\u GNU_SOURCE
,手动关闭它将打开libstdc++。显然,libstdc++依赖于其他头文件中的特定定义,这些头文件仅在定义了
\u GNU\u SOURCE
时才会显示。是否确实没有头文件或3。派对标题定义了例如
\u GNU\u SOURCE
?你很有趣。第二句话让我笑了。哇,我简直不敢相信我刚打了LOL'ing,该死的,又来了。你会以为我13岁就在打字。呸,这可能只是一夜之间喝了太多啤酒和进行了太多的单元测试。另一个类似这样的函数,带有一个可笑的
\r
变体,就是
readdir
。有一个非常好的
DIR
结构来包含缓冲区(或者一个指向动态分配的每个线程缓冲区的指针,如果人们真的坚持从多个线程读取单个
DIR
),并且绝对没有理由添加
readdir\r
(带有笨拙的界面)。手册页甚至列出了一些示例:“未知错误NNN“。这没有翻译。FWIW该标准已更新为要求
readdir
是线程安全的。希望下一个是
strerror
。@o11c:事实上,生成的无效错误号消息是返回不可变字符串的明显情况。我提议的一个标准化折衷方案是要求
strerror
只有在传递给它的错误号有效时才是线程安全的。当我们谈论userland时,为什么要给出内核版本?
#include <string.h>
#ifdef _GNU_SOURCE
#error "Something turned it on!"
#endif
#ifdef _GNU_SOURCE
#undef _GNU_SOURCE
#endif
#include <string.h>
#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;
}
#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