2

I have seen strdup used in code samples on StackOverflow and have just tried to use it on Linux (3.0.0-21-generic x86_64).

The compiler (clang) knew it was in string.h, but still complained about not having a prototype even with string.h included. It turns out that strdup is wrapped in a #if defined, in string.h. I searched this site and found a post that said that strdup is a POSIX routine, not a C standard library routine.

The possible macros that will expose it are

  • __USE_SVID
  • __USE_BSD
  • __USE_XOPEN_EXTENDED
  • __USE_XOPEN2K8

Each one of those is undefined in features.h which is included by stdlib.h.

Why isn't a POSIX macro in that list and which macro/compiler switch are people using to expose strdup in string.h?

Edit: per Jim's comment below I found that

#define _POSIX_SOURCE 1 

or

#define _POSIX_C_SOURCE 1

above

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

do not expose strdup on my system.

But these do:

#define _BSD_SOURCE 1
#define _SVID_SOURCE 1

Edit 2: Per Keith's comment, I found that this also works:

#define _POSIX_C_SOURCE 200809L

Edit 3: Per Jonathan's comment these also work

#define _XOPEN_SOURCE 500
#define _XOPEN_SOURCE 600
#define _XOPEN_SOURCE 700
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Scooter
  • 6,802
  • 8
  • 41
  • 64
  • 2
    You should certainly find it with `#define _XOPEN_SOURCE 700` (which is equivalent to asking for POSIX 2008), and since it was in X/Open back in 1997, you should be OK with values of 500 or 600 too. – Jonathan Leffler Sep 25 '12 at 03:29
  • @JonathanLeffler Yes, all three work. I will edit them in. – Scooter Sep 25 '12 at 03:37

1 Answers1

3

The __USE... macros are for internal use. You should define _POSIX_SOURCE, or possibly one of the other feature macros as described in the comments in your feature.h ... for example, from a version I just grabbed off the web (apparently an old and somewhat obsolete version),

   __STRICT_ANSI__  ANSI Standard C.
   _POSIX_SOURCE    IEEE Std 1003.1.
   _POSIX_C_SOURCE  If ==1, like _POSIX_SOURCE; if ==2 add IEEE Std 1003.2.
   _BSD_SOURCE      ANSI, POSIX, and 4.3BSD things.
   _SVID_SOURCE     ANSI, POSIX, and SVID things.
   _GNU_SOURCE      All of the above, plus GNU extensions.

So defining _GNU_SOURCE would get you everything.

Edit: from the comment by Keith Thompson, you need

 #define _POSIX_C_SOURCE 200809L

for strdup.

Jim Balter
  • 16,163
  • 3
  • 43
  • 66
  • If I put #define _POSIX_SOURCE 1 or #define _POSIX_C_SOURCE 1 at the top of my program, it doesn't expose it. stdlib.h, string.h and stdio.h are included below it. But _BSD_SOURCE and _SVID_SOURCE work. – Scooter Sep 25 '12 at 02:10
  • 1
    According to the man page on my system, you need `#define _POSIX_C_SOURCE 200809L` (which works for me). – Keith Thompson Sep 25 '12 at 02:16
  • 1
    In [this thread](http://stackoverflow.com/questions/482375/strdup-function) someone mentions the argument that "if there is a two lines simple, guaranteed working way - why should one depend on not portable functions?" – Douglas B. Staple Sep 25 '12 at 02:19
  • @DouglasB.Staple: Agreed. On the other hand, `strdup` is defined by POSIX; if the rest of your program depends on POSIX, there's no strong reason not to use `strdup()`. – Keith Thompson Sep 25 '12 at 02:31
  • @DouglasB.Staple I think even better taken is the comment by Chaim Geretz to the answer by Pat on that page. – Jim Balter Sep 25 '12 at 02:34
  • @JimBalter malloc failing in your own routine doesn't seem any different than malloc failing when strdup calls it. In either case the caller has to check for NULL. – Scooter Sep 25 '12 at 02:55
  • 1
    @Scooter You have missed the point. Didn't you stop to wonder why that comment got 9 upvotes? Pat wrote his/her own version of strdup, which has a glaring bug in it ... it doesn't check malloc for failure, and if malloc fails you get undefined behavior (most likely a segvio) ... it doesn't just pass the NULL back to the caller of strdup. Perhaps Pat made the same error in thinking that you did. The point is, the library version of strdup won't have such a bug. – Jim Balter Sep 25 '12 at 03:02
  • @JimBalter I think the point is that it is a small function, easily implemented. The poster made an error in trying to make it as small as possible, but the wiley reader will not let that distract him/her from the point being made. – Scooter Sep 25 '12 at 03:06
  • @Scooter You talk about "the" point while completely ignoring the one that I, and Chaim Geretz (upvoted 9 times) made: it's easily implemented wrongly! And you yourself misunderstood the logic, not seeing the bug. You may not grasp how important this is now, but give yourself a few years (I've been programming for 47, 35 of them in C). – Jim Balter Sep 25 '12 at 03:09
  • @JimBalter I didn't misunderstand the logic. I never commented that his logic was correct as written. I said "malloc failing in your own routine doesn't seem any different than malloc failing when strdup calls it." – Scooter Sep 25 '12 at 03:12
  • @Scooter On second reading, perhaps you didn't miss the bug. But the rest stands ... when discussing various points in an argument, it is bad faith to refer to "the" point while completely ignoring the point the other side is making. " doesn't seem any different " -- ah, but it is ... there are *two* places that it must be checked if you write your own. Over and out. – Jim Balter Sep 25 '12 at 03:13
  • `_POSIX_SOURCE` is deprecated (it was only for the original POSIX standard), and `_POSIX_C_SOURCE` should have values of the form `yyyymmL` (filled in with the date of the standard you want to use, e.g. `200809L`). – R.. GitHub STOP HELPING ICE Sep 25 '12 at 03:51