【问题标题】:mkdtemp requires _DARWIN_C_SOURCE for unistd.hmkdtemp 需要 _DARWIN_C_SOURCE 用于 unistd.h
【发布时间】:2012-07-11 13:13:42
【问题描述】:

我有点疑惑。我有我编译的项目

CFLAGS=-g -O2 -Wall -Wextra -Isrc/main -pthread -rdynamic -DNDEBUG $(OPTFLAGS) -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700

现在我想使用mkdtemp,因此包括unistd.h

char *path = mkdtemp(strdup("/tmp/test-XXXXXX"));

在 MacOSX 上,编译会给出一些警告

warning: implicit declaration of function ‘mkdtemp’
warning: initialization makes pointer from integer without a cast

但编译通过。虽然 mkdtemp 确实返回了一个非 NULL 路径,但访问它会导致 EXC_BAD_ACCESS。

问题一:模板为strdup()ed,结果非NULL。这到底怎么会导致 EXC_BAD_ACCESS?

现在在兔子洞的更深处。让我们摆脱警告。检查unistd.h我发现声明被预处理器隐藏了。

#if     !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
...
char    *mkdtemp(char *);
...
#endif

-D_DARWIN_C_SOURCE 添加到构建中可以消除所有问题,但给我留下了特定于平台的构建。 10.6 手册页只是说

 Standard C Library (libc, -lc)
 #include <unistd.h>

从构建中删除 _XOPEN_SOURCE 在 OSX 上是可行的,但在 Linux 下无法编译

warning: ‘struct FTW’ declared inside parameter list
warning: its scope is only this definition or declaration, which is probably not what you want
In function ‘tmp_remove’:
warning: implicit declaration of function ‘nftw’
error: ‘FTW_DEPTH’ undeclared (first use in this function)
error: (Each undeclared identifier is reported only once
error: for each function it appears in.)
error: ‘FTW_PHYS’ undeclared (first use in this function)

问题 2:那么您将如何解决这个问题?

我发现的唯一解决方法是 #undef _POSIX_C_SOURCE 在 unistd.h 包含之前...但这感觉就像一个丑陋的黑客。

【问题讨论】:

  • mkdtemp 不是基本 POSIX ——根据pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html,它位于扩展 API 中。段错误:你确定你
  • 你传入的是 char * 而不是 const char *?
  • 我知道 mkdtemp 不是基础 POSIX。但似乎_XOPEN_SOURCE 导致_POSIX_C_SOURCE 被定义。仍然想使用mkdtempftw API。
  • 至于const char* 见上文。这是通过strdup 复制的文字。所以应该没问题。
  • @H2CO3 er,CX 那里实际上意味着它在 POSIX 中,但不在 ANSI C 中。问题是 OSX 显然不支持它添加的 POSIX 版本。

标签: c linux macos posix


【解决方案1】:

你在这里问了两个问题,我只回答第一个:

问题1:模板是strdup()ed,结果非NULL。这到底怎么会导致 EXC_BAD_ACCESS?

正如上面的警告告诉你的那样:

警告:函数“mkdtemp”的隐式声明

这意味着它找不到mkdtemp 的声明。根据 C 规则,这是允许的,但它假设函数返回一个 int。

警告:初始化使指针从整数而不进行强制转换

您已经告诉编译器“我有一个返回 int 的函数,我想将值存储在 char* 中”。它警告你这是一个坏主意。你仍然可以这样做,因此它可以编译。

但是想想运行时会发生什么。您链接到的实际代码返回 64 位 char*。然后您的代码将其视为必须转换为 64 位 char* 的 32 位 int。这样做的可能性有多大?

这就是您不忽略警告的原因。

【讨论】:

  • 由于其他问题似乎没有简单的答案,我接受了这个问题。
【解决方案2】:

现在是第二个问题:

问题 2:那么您将如何解决这个问题?

您的问题是您明确传递了 -D_XOPEN_SOURCE=700,但您使用的函数 mkdtemp 未在您要求的标准中定义。这意味着您的代码不应该工作。它在 linux 上运行的事实并不意味着你的代码是正确的或可移植的,只是你碰巧在一个平台上很幸运。

因此,有两种相当明显的方法可以解决此问题:

  1. 如果您想使用 _XOPEN_SOURCE=700,请重写您的代码以仅使用该标准中的函数。

  2. 如果您只是将 _XOPEN_SOURCE=700 添加为一个您并不真正理解的 hack,因为它似乎可以解决 linux 上的一些其他问题,请找到在 linux 上解决该问题的正确方法。

结果可能是在一个或另一个平台上存在错误,因此没有正确的方法来修复它。或者,更有可能的是,您正在使用可以在不同平台上压缩的非标准函数的组合,每个平台上都有一组不同的标志。在这种情况下,您的 Makefile(或任何驱动构建的文件)将必须将不同的标志传递给不同平台上的编译器。这对于跨平台项目来说是非常典型的;很高兴您只需要担心一个标志,并且没有构建价值 3000 行的 autoconf。

【讨论】:

  • 我只添加了_XOPEN_SOURCE,因为我想使用ftw API。显然这也迫使_POSIX_C_SOURCE。有没有什么标准的概述?
  • 好吧,unix.com/man-page/Linux/7/feature_test_macros 的 linux 手册页有很多信息……就像最近的 OpenGroup 标准 (pubs.opengroup.org/onlinepubs/9699919799/functions/…) 的第 1 和 2.2 节一样。但一切都在一个地方?可悲的是,我不知道。 (此外,Linux 和 OS X 都包含许多扩展,这些扩展可能会出现在它们当前支持的标准之外的下一个标准中,等等。)同时,FTW 在 XOpen 7 中并不是新的——事实上,它在 XOpen 中被标记为过时的7——所以我不确定这是引入它的正确方法。
  • 首先 - 感谢您的链接!很有用。 ftw 标记为已过时? sigh 打开罐头 - 蠕虫 - 无处不在。最初我使用fts API,但在Linux 上编译我最终得到#error "&lt;fts.h&gt; cannot be used with -D_FILE_OFFSET_BITS==64"
  • IIRC,fts 是一个 linux 复制的 BSD 扩展,但仍未登陆 POSIX,这意味着即使它有效,您最终可能会得到“可移植”的代码linux 和 *BSD(包括 OS X),但别无他法,这是自欺欺人的好方法……这里可悲的答案是没有完全可移植的完整替代方案。这意味着您将不得不进行一些可移植性黑客攻击。在 Makefile 中进行单行平台检查比大多数项目必须处理的痛苦要少得多……
  • 鉴于我现阶段只关心 Linux 和 OS X - 现在没关系。不使用 _FILE_OFFSET_BITS 是一个不错的妥协,可以让我逃离那个“地狱”。谢谢你的意见,伙计们。
猜你喜欢
  • 2019-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 2018-09-25
  • 2021-10-09
相关资源
最近更新 更多