【问题标题】:libc include guards not respecting source type parameter changeslibc 包含不遵守源类型参数更改的守卫
【发布时间】:2019-10-22 13:52:36
【问题描述】:

问题

如果我包含time.h,更改“源类型参数”并重新包含该标题,它不应该添加这些新定义吗?我知道这是由于包括警卫而发生的。我的问题是:这是 libc 中的错误吗?它不应该能够处理吗?

#include <time.h>
#define _XOPEN_SOURCE 600
#include <time.h>

static struct timespec t;

错误信息:

example.c:5:24: error: storage size of ‘t’ isn’t known
    5 | static struct timespec t;
      |                        ^

背景

我在使用 -std=c99 编译时发现了这种构建 Python 扩展的行为。如果我在包含 Python.h 之前包含标准库,我会因为缺少 POSIX 功能的定义而出现编译错误。如果我将Python.h 包含在其他所有内容之前,一切都很好。当然,使用-std=gnu99 编译也可以。但我想深入了解错误发生的原因,并将其提炼为上述代码示例。

这引出了另一个问题。如果上述行为不是错误,那么在标头中设置 _XOPEN_SOURCE 和类似的源类型参数是否被认为是不好的做法? Python 是否应该在其标头中删除该参数的设置,而是要求用户在编译期间定义它,还是使用std=gnu99

【问题讨论】:

  • “如果我包含 time.h,更改“源类型参数”并重新包含该标头,它不应该添加到那些新定义中吗?” 不,实际上恰恰相反。守卫在那里,所以你不会第二次宣布什么。因此,“旧”定义会保留下来,不会被覆盖。

标签: c libc


【解决方案1】:

您所说的“源类型参数”称为功能测试宏,如果已定义,则特别需要在包含 任何 标准标头之前对其进行定义。

这是在XSH 2.2.1 POSIX.1 Symbols中指定的:

符合 POSIX 的应用程序应确保在包含任何标头之前定义功能测试宏 _POSIX_C_SOURCE。

...

符合 XSI 的应用程序应确保在包含任何标头之前使用值 700 定义功能测试宏 _XOPEN_SOURCE。

Linux man page for feature-test-macros 还明确说明了对标准及其扩展的要求:

注意:为了有效,功能测试宏必须在包含任何头文件之前定义

您不能重新定义和重新包含标题来更改内容,实际上在标题之间定义或取消定义/重新定义它们(即使是不同的,看似不相关的标题)可能会完全破坏事物。

【讨论】:

  • 所以这意味着它可能缺少 Python 文档。他们应该声明 Python 依赖于 POSIX 标准,扩展模块应该使用 -std=gnu99-D_XOPEN_SOURCE 编译。
  • 我不认为这是 Python 文档的问题。如果您想使用-std=c99 进行编译,但需要 POSIX 或更多功能,则需要使用 FTM 来获取它。我认为这记录在 GCC 中。首选方法是在您添加-std=c99(在CFLAGS 中)的任何位置添加正确的-D,而不是编辑源。然后确保在包含任何标题之前定义它。
  • 这是一个文档问题。我没有使用 POSIX,Python 是,它 假设 它在那里。因为没有文档另有说明,所以我认为使用 C99 并重新排序包含是可以接受的,但不是。
  • 我明白了。那么是的,Python 应该记录您需要使用带有适当 FTM 的 Python 头文件/接口来编译模块源,以使 POSIX 基线(或 XSI 或其他)功能可用,并提及它们需要在文件顶部或通过 @ 定义987654330@.
猜你喜欢
  • 2013-03-31
  • 1970-01-01
  • 2012-01-19
  • 2021-01-29
  • 2019-04-25
  • 2017-07-31
  • 2011-01-24
  • 2022-01-22
相关资源
最近更新 更多