strdup(): Confused about warnings ('implicit declaration', 'makes pointer...without a cast', memory leak)
The C standard library does not have such function as strdup
. Nevertheless this popular function is usually provided by standard library implementations as an extension. In GCC implementation this function is declared in <string.h>
, which you do include.
However, when you compile your code with stricter standard settings, like -std=c99
, the compiler hides non-standard function declarations made in standard library headers. This is what happened to strdup
declaration in your case. The warning that you get is a typical warning that is issued when you attempt to call an undeclared function. Formally, this is an error from C99 point of view, but your compiler decided that a warning is sufficient in this case. If you remove the -std=c99
switch from the compiler's command line, the declaration of strdup
will become visible and the code will compile without that warning.
More technically, specifying -std=c99
in the command line makes GCC to define __STRICT_ANSI__
macro, which causes all non-ANSI function declarations to "disappear" from the standard headers.
The function is still present in the library, which is why your code links properly. Note that it does not necessarily run properly, since the compiler assumed that strdup
returned an int
, when in reality it returns a pointer.
The valgrind report is just a consequence of memory leak. strdup
allocates memory that you are supposed to free
yourself when you no longer need it.
strdup()
isn't standard C. It is a POSIX extension.
To make strdup()
available even with strict C99 compliance for GCC when using the option -std=c99
you need to #define
at least one of the following:
_SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500
|| _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
(taken from strdup()
's Linux man-page)
by coding for example (before including <string.h>
):
#define _SVID_SOURCE
or:
#define _POSIX_C_SOURCE 200809L
Alternatively you can pass those defines via GCC's command-line as option
-D_SVID_SOURCE
or
-D_POSIX_C_SOURCE=200809L