我有点困惑。我有一个编译项目
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。
问题 1:模板经过 strdup()
处理,结果为非 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:那么您将如何解决这个问题?
我发现的唯一修复方法是在 unistd.h
之前包含 #undef
_POSIX_C_SOURCE ...但这感觉像是一个丑陋的黑客。
最佳答案
您在这里问了两个问题,我只回答第一个问题:
Question 1: The template is strdup()ed and the result is non-NULL. How on earth can this result in an EXC_BAD_ACCESS?
正如上面的警告告诉您的那样:
warning: implicit declaration of function ‘mkdtemp’
这意味着它找不到 mkdtemp
的声明。根据 C 规则,这是允许的,但假设该函数返回一个 int。
warning: initialization makes pointer from integer without a cast
您已经告诉编译器“我有一个返回 int 的函数,并且我想将值存储在 char* 中”。它警告您这是一个坏主意。您仍然可以这样做,因此它可以编译。
但是想想运行时会发生什么。您链接到的实际代码返回 64 位 char*。然后您的代码将其视为 32 位 int,必须将其转换为 64 位 char*。这可行的可能性有多大?
这就是为什么您不忽略警告的原因。
关于c - mkdtemp 需要 _DARWIN_C_SOURCE for unistd.h,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11440787/