I am a little puzzled. I have project that I compile with
CFLAGS=-g -O2 -Wall -Wextra -Isrc/main -pthread -rdynamic -DNDEBUG $(OPTFLAGS) -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700
Now I want to use mkdtemp and therefor include unistd.h
char *path = mkdtemp(strdup("/tmp/test-XXXXXX"));
On MacOSX the compilation gives some warnings
warning: implicit declaration of function ‘mkdtemp’
warning: initialization makes pointer from integer without a cast
but compiles through. While mkdtemp does return a non-NULL path accessing it results in a EXC_BAD_ACCESS.
Question 1: The template is strdup()ed and the result is non-NULL. How on earth can this result in an EXC_BAD_ACCESS?
Now further down the rabbit hole. Let’s get rid of the warnings. Checking unistd.h I find the declaration hidden by the pre processor.
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
...
char *mkdtemp(char *);
...
#endif
Adding -D_DARWIN_C_SOURCE to the build makes all the problems go away but leaves me with a platform specific build. The 10.6 man page just says
Standard C Library (libc, -lc)
#include <unistd.h>
Removing the _XOPEN_SOURCE from the build makes is work on OSX but then it fails to compile under Linux with
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)
Question 2: So how would you fix this?
The only fix I have found is to #undef _POSIX_C_SOURCE right before the unistd.h include …but that feels like an ugly hack.
You’ve asked two questions here, and I’m just going to answer the first:
As the warnings above tell you:
This means it couldn’t find the declaration for
mkdtemp. By C rules, that’s allowed, but it’s assuming the function returns an int.You’ve told the compiler “I’ve got a function that returns int, and I want to store the value in a char*”. It’s warning you that this is a bad idea. You can still do it, and therefore it compiles.
But think about what happens at runtime. The actual code you link to returns a 64-bit char*. Then your code treats that as a 32-bit int that it has to cast to a 64-bit char*. How likely is that to work?
This is why you don’t ignore warnings.