12

如何获得 POSIX strerror_r而不是 GNU 版本?

我正在使用 glibc 版本 2.7 的 Ubuntu 8.04 上使用 g++ 进行编译(基于其中的内容)。

编辑

在上面的手册页上它说:

glibc 的功能测试宏要求(参见 feature_test_macros(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 版本。

4

3 回答 3

9

从标题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 版本受到青睐。

我能想到的唯一能做到的就是_GNU_SOURCE。我确定这不在您的命令行标志上,您会看到它。可能是包含的另一个库已将其打开。

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

编辑

如果某些东西正在开启_GNU_SOURCE(我不记得 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;
}

问题是,当您的代码实际包含string.h时,其他东西已经打开了扩展并包含了它。包含警卫自然会阻止您将其包含两次。

尝试在其他任何事情之前明确关闭_GNU_SOURCE并包括在内。这可以防止其他库打开这些扩展。但是,如果没有它们,这些库可能无法工作。一些代码只是“预期”GNU 行为,不包括回退到 POSIX。string.h

我对没有asprintf().

于 2010-06-16T09:30:41.060 回答
4

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

#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
于 2013-08-28T13:39:31.193 回答
2

While it's not required to be thread-safe by the standard, I can't imagine any way a sane person could write a non-thread-safe strerror. What do people do, gunzip the error strings at runtime or something?! A good strerror should be returning a pointer either to string constants in the standard library, or to constant mmap'd memory from the locale messages file.

Apologies that this isn't a real answer, but if you don't care about absolute theoretical portability you might check and see if all the implementations you care about have sane strerror behavior, and if so, just use that instead.

于 2010-11-17T22:40:37.253 回答