70

When I use strdup in Microsoft Visual C++, it warns me:

warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details.

Thus it seems _strdup is correct.

But when I use _strdup in GCC (Fedora Linux OS), the compiler shows an error:

error: ‘_strdup’ was not declared in this scope

With GCC and Linux, compiler does not show any error for strdup.

Which is correct - strdup or _strdup?

Note: I include <string.h> in my code.

jrh
  • 405
  • 2
  • 10
  • 29
Amir Saniyan
  • 13,014
  • 20
  • 92
  • 137
  • 4
    In C++, consider using `std::string` instead of C-style strings, then the issue goes away. Also, in C++, the header is simply ``. – johnsyweb Sep 28 '11 at 11:23
  • 1
    @Rowland Shaw: I mean GCC shows an error for `_strdup` but does not show any error for `strdup`. My test platform was Fedora Linux. – Amir Saniyan Sep 28 '11 at 11:30
  • 1
    Note that in Visual Studio 2013 onward, these warnings are now errors. – jrh Oct 12 '16 at 11:25

7 Answers7

46

Which is correct?

strdup is a perfectly correct POSIX function. Nevertheless, it doesn't belong to the standard, and the ANSI C standard reserves some (broad) classes of function names for further use. Among these, there are

  • Function names that begin with str and a lowercase letter

therefore, the MS guys decided to replace strdup with _strdup.

I'd just continue using strdup. It's unlikely the C committee will define strdup to something else than POSIX. Either #define strdup _strdup or silence the warning.

BTW I hope you see this applies to your functions with names like string_list etc., too.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • 1
    It seems that, different to POSIX, ISO C will likely never define `strdup` in near future. See [N1118](http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1118.htm) about "no-implicit-malloc rule". – FrankHB Aug 13 '16 at 06:43
  • 1
    @FrankHB: never says *never*! `strdup` is finally making its way into the next C Standard: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf but I guess you were right about *near future*, in the C world, 10 years is quick. – chqrlie Mar 30 '20 at 12:16
  • 1
    I have been aware of that for years. Interesting to see WG14 breaking their implicit rules. – FrankHB Mar 31 '20 at 05:16
  • C2x likely will employ `strdup()`, but not with the same exact functionality of POSIX nor MS `strdup()`. `_strdup()` is the was to go. – chux - Reinstate Monica Dec 28 '22 at 22:05
  • @chux-ReinstateMonica *not with the same exact functionality* [Seems identical to me in this C23 draft](https://www.iso-9899.info/n3047.html#7.26.2.6): "The strdup function creates a copy of the string pointed to by s in a space allocated as if by a call to malloc." – Andrew Henle May 21 '23 at 14:32
  • @AndrewHenle At least this difference: `errno`. A common existing [`strdup()`](https://man7.org/linux/man-pages/man3/strdup.3.html) has "It returns `NULL` if insufficient memory was available, with `errno` set to indicate the error." Your linked [C23](https://www.iso-9899.info/n3047.html#7.26.2.6) does not specify setting `errno`. – chux - Reinstate Monica May 21 '23 at 17:11
  • jpalecek, "It's unlikely the C committee will define strdup to something else than POSIX." is incorrect given the state of `errno`. The current C23 proposal vs. POSIX differs on that. – chux - Reinstate Monica May 21 '23 at 17:16
  • @chux-ReinstateMonica The C standard doesn't specify setting `errno` for [`fopen()`](https://port70.net/~nsz/c/c11/n1570.html#7.21.5.3), either. Nor [`printf()`](https://port70.net/~nsz/c/c11/n1570.html#7.21.6.3). Thus implementations of those functions [are free to do whatever they want to `errno` under any circumstances](https://port70.net/~nsz/c/c11/n1570.html#7.5p3): "The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in this International Standard." – Andrew Henle May 21 '23 at 17:33
  • (cont) Thus, POSIX-compliant implementations that set `errno` on error are strictly-conformant to the C standard. C23 is the same. – Andrew Henle May 21 '23 at 17:34
  • @AndrewHenle True, yet the [comment](https://stackoverflow.com/questions/7582394/strdup-or-strdup/7582741?noredirect=1#comment132256076_7582741) was not _conformance_ of POSIX to C23, but is the C23 spec the same as POSIX - it is not. Citing those two as exactly same fails when someone uses the POSIX definition in C23 with dependence on `errno` in a non-POSIX setting. When writing portable code with `strdup()` and C23, we lose `errno` specifity. IMO, I hoped C23 would have added `ENOMEM` or the like to the various `*alloc()` functions - including `strdup()` to remove that difference. – chux - Reinstate Monica May 21 '23 at 20:48
35

strdup is not a standard C++ function. But it is apparently a POSIX function, and anyway it's a well known function which has been there since K&R C. So if you absolutely must use it, do not fret about any possible name collision, and just write strdup for maximum portability.

rturrado
  • 7,699
  • 6
  • 42
  • 62
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 5
    The problem is, there is a plethora of "POSIX-compliant _foo's in MSVC. It is very annoying, if you want both "quiet compilation" (espacially in large projects), and a possibility to port it to GCC. For example _fileno, _isatty (when playing with Flex parser generator), and lots of other system functions. Currently I add many #defines inside #ifdef _MSC_VER, but I'm always open for a better solution. – Tomasz Gandor Aug 05 '13 at 12:17
  • 4
    @ThomasGandor: one alternative to `#ifdef` is to use compiler-specific header selection via the compiler's header include file search path. one alternative to `#define` (since macros don't respect scopes) is to use `inline` forwarder functions. – Cheers and hth. - Alf Aug 07 '13 at 02:41
  • 22
    Simply use `-D_CRT_NONSTDC_NO_DEPRECATE`. It should work anywhere, and for MSVC it will make it shut up. Its sole purpose is to annoy the hell out of the user when porting applications. It might also have some use cases where an MSVCRT variant behaves differently than the POSIX/C99 variant. I can't think of any at the moment though – Mark Nunberg Jun 25 '14 at 23:55
  • 4
    @mnunberg: _snprintf() Check the documentation carefully. – Zan Lynx Jul 28 '14 at 21:40
  • 2
    For extra insanity, VS2015 makes these *errors*, and you have to use multiple nonstandard #defines to get normal behavior back. – Glenn Maynard Aug 21 '16 at 02:48
  • @GlennMaynard: Use of `strdup` (no underscore prefix) compiled with a warning with Visual C++ 2015 update 2. Adding the `-D_CRT_NONSTDC_NO_DEPRECATE` option got rid of the warning. – Cheers and hth. - Alf Aug 21 '16 at 02:59
  • 2
    No, some of these broken "deprecation" warnings are actually errors now, like open(). It's no longer just setting #defines to quiet bogus warnings, now you have to set them if you want your application to compile at all. I had to set these just to get zlib to build, and that's probably among the three or four most widely-used libraries in the world. – Glenn Maynard Aug 21 '16 at 03:13
  • 1
    @GlennMaynard: Also call to `open` compiles fine on my machine, with MSVC 2015 update 2. The compiler reports version number 19.00.23725. However, for `open` getting rid of the warnings requires two defines, `/D _CRT_NONSTDC_NO_DEPRECATE /D _CRT_SECURE_NO_WARNINGS`. – Cheers and hth. - Alf Aug 21 '16 at 03:29
  • 1
    For MSVC++ 2015 update 3, I have disabled SDL checks and goes further, in C/C++ > General> SDL checks. – mike Sep 08 '16 at 13:12
  • According to VS2015 (Update 3), the ISO C and C++ conformant name is in fact `_strdup`. Why has this not been addressed in the comments at all? If the VS compiler error message is correct, the answer is not only wrong, but also perpetuates incorrect dogma. – average joe Oct 14 '16 at 14:14
  • @averagejoe: `_strdup` is a conforming name (when provided by the compiler vendor), and this is information is prominently displayed in the question. It's **what the question is about**, and that's why it's not repeated in the answer or in the comments: everybody so far has understood what the question was. The problem is whether to use the conforming name, which not all vendors provide, or use the classic Posix name. And my advice here was to recognize that no practically useful 3rd party code will introduce a name conflict for `strdup`. It would be different for a less known function. – Cheers and hth. - Alf Oct 14 '16 at 14:23
  • @averagejoe, `_strdup` is conformant to C++, but it's not conformant to C (emphasis mine): _All identifiers that begin with an underscore are always reserved for use as identifiers **with file scope** in both the ordinary and tag name spaces._ At least on the computer I'm on, microsoft's `string.h` defines `_strdup` as a function with external linkage, violating conformance with C. – Shahbaz Jan 10 '17 at 15:53
  • 1
    @Shahbaz: It's reserved for the implementation. The implementation can use identifiers of that form freely, that's what the reservation is about. `` is part of the implementation. – Cheers and hth. - Alf Jan 10 '17 at 16:03
  • @Cheersandhth.-Alf, you're talking about C++. – Shahbaz Jan 10 '17 at 18:26
  • C++ has the same rule, and it means the same. Think about it. For whom are those identifiers reserved if not for the implementation? Brian Kernighan? – Cheers and hth. - Alf Jan 10 '17 at 23:37
  • Sadly microsoft don't give a damn. – Owl Oct 10 '18 at 15:00
28

You can #define _CRT_NONSTDC_NO_DEPRECATE to disable this warning.

David Bremner
  • 396
  • 5
  • 8
13

If you just want to avoid the Warning message:

Project-> property -> C/C++ -> Preprocessor -> Preprocessor Definitions

Edit this, and add

_CRT_NONSTDC_NO_DEPRECATE

Darós
  • 158
  • 1
  • 3
  • 9
9

strdup is POSIX:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html

_strdup is Windows specific:

http://msdn.microsoft.com/en-us/library/y471khhc(v=vs.80).aspx

On Unix, use strdup. On Windows, use _strdup. It's that simple. If you need to write portable code between Unix and Windows:

  • use system dependent macros (for example _WIN32 vs. _POSIX_VERSION) to select the proper function (but notice that the macros may depend on specific pre existing include files):

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html

http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.80).aspx

  • use standard functions to reimplement strdup: strlen, malloc and memmove.

  • use a cross platform utility library, like glib:

http://developer.gnome.org/glib/2.28/glib-String-Utility-Functions.html#g-strdup

Note that Visual C++ message suggests that _strdup belongs to the C++ standard, but this is false, as it can be verified on the C++ standard. It merely uses the underscore prefix as a "namespace" for the function.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf

hdante
  • 7,685
  • 3
  • 31
  • 36
  • 11
    `MSVC` never suggest that `_strdup` belongs to C++ standard! it just say `_strdup` is a name that conform to C++ standard. As you and others said, `strdup` is a reserved name that used by `POSIX` systems, so MS think it could solve the problem of reserved name – BigBoss Jun 09 '13 at 03:15
5

Don't know about C++.

The C Standard does not describe any function with the strdup name (though the name is reserved). To be portable, in C, you're better off replacing that with malloc, strcpy, and free.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • I agree with this. The function is, and has always been, redundant. – Lundin Sep 28 '11 at 12:50
  • I just checked the (probable) [next C Standard](http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1548.pdf) (*C2011*?) and `strdup` is not described by it either. – pmg Sep 28 '11 at 13:36
  • 2
    @pmg: 10 years later, `strdup` will finally make its way into the next C Standard: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2479.pdf but I guess in the C Standard world, 10 years is quick. – chqrlie Mar 30 '20 at 12:19
0

it's not a warning but an error reported in higher version of vs.

use macro #ifdef WIN32 to switch

yjjjnls
  • 62
  • 5