Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strdup(): Confused about warnings ('implicit declaration', 'makes pointer...without a cast', memory leak)

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)
like image 572
iceman Avatar asked Oct 09 '14 17:10

iceman


People also ask

How does strdup work in C?

strdup() :This function returns a pointer to a null-terminated byte string, which is a duplicate of the string pointed to by s. The memory obtained is done dynamically using malloc and hence it can be freed using free(). It returns a pointer to the duplicated string s.

What does strdup return?

The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3). The strndup() function is similar, but copies at most n bytes.

What is the difference between strdup and Strcpy?

Difference between strdup() and strcpy()The function strcpy() will not allocate the memory space to copy. A pointer to the string to copy and a pointer to place to copy it to should be given. The function strdup() will occupy / grab itself the memory space for copying the string to.

How is strdup implemented?

In the case of strdup, we use a specific function, malloc(), to allocate the memory dynamically. But it is favorable if you delete the content or free the space after usage. So for this purpose, simply use strdup() with malloc(), and then copy the source string to the allocated memory.


3 Answers

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.

like image 85
AnT Avatar answered Oct 07 '22 09:10

AnT


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
like image 34
alk Avatar answered Oct 07 '22 10:10

alk


As AnT already said, when you use the flag "-std=c99" the compiler hides all non-standard function in the header "string.h"

One way to fix it is to add this line of code, at the beggining of your code (or wherever you want, as long as it is before using the strdup function)

extern char* strdup(const char*);

like image 1
user3325706 Avatar answered Oct 07 '22 09:10

user3325706