When I compile the short piece of code below (in which we define a string and then use strdup to make a copy), I get 3 warnings: 2 compiler warnings from GCC and 1 run-time warning/error from valgrind.
I suspect the memory leak error (reported by valgrind) is also related to my use of strdup, which is why I'm including the relevant output below.
What am I doing wrong? (I'm working my way through a C book and this is how strdup is used by the author.)
The code:
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char *string1 = "I love lamp";
char *string2;
string2 = strdup(string1);
printf("Here's string 1: %s\n"
"Here's string 2: %s\n",
string1, string2);
return 0;
}
The warnings/output:
dchaudh@dchaudhUbuntu:~/workspaceC/LearnCHW/Ex17_StructsPointers$ make test
cc -std=c99 test.c -o test
test.c: In function ‘main’:
test.c:9:3: warning: implicit declaration of function ‘strdup’ [-Wimplicit-function-declaration]
string2 = strdup(string1);
^
test.c:9:11: warning: assignment makes pointer from integer without a cast [enabled by default]
string2 = strdup(string1);
^
dchaudh@dchaudhUbuntu:~/workspaceC/LearnCHW/Ex17_StructsPointers$ valgrind --track-origins=yes --leak-check=full ./test
==3122== Memcheck, a memory error detector
==3122== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3122== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==3122== Command: ./test
==3122==
Here's string 1: I love lamp
Here's string 2: I love lamp
==3122==
==3122== HEAP SUMMARY:
==3122== in use at exit: 12 bytes in 1 blocks
==3122== total heap usage: 1 allocs, 0 frees, 12 bytes allocated
==3122==
==3122== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3122== at 0x4C2ABBD: malloc (vg_replace_malloc.c:296)
==3122== by 0x4EBF2B9: strdup (strdup.c:42)
==3122== by 0x4005A4: main (in /home/dchaudh/workspaceC/LearnCHW/Ex17_StructsPointers/test)
==3122==
==3122== LEAK SUMMARY:
==3122== definitely lost: 12 bytes in 1 blocks
==3122== indirectly lost: 0 bytes in 0 blocks
==3122== possibly lost: 0 bytes in 0 blocks
==3122== still reachable: 0 bytes in 0 blocks
==3122== suppressed: 0 bytes in 0 blocks
==3122==
==3122== For counts of detected and suppressed errors, rerun with: -v
==3122== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
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 tostrdup
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 ofstrdup
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 anint
, when in reality it returns a pointer.The valgrind report is just a consequence of memory leak.
strdup
allocates memory that you are supposed tofree
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:(taken from
strdup()
's Linux man-page)by coding for example (before including
<string.h>
):or:
Alternativly you can pass those defines via GCC's command-line as option
or
Your compiler doesn't have a declaration of strdup, because you didn't #include any header file declaring it.
Having no declaration, the compiler guessed that strdup would return an int. You assign the result of calling strdup to a pointer variable.
Include the right header file, and your problems should at least get less.