Search code examples
ccross-platformposix

Why do Windows and Linux have different strdup implementations: strdup() and _strdup()?


When working with strdup on Windows I found out that _strdup is Windows specific, but when I ran the same code on Linux it required strdup without the underscore. Does anyone know the history behind this difference, as-well as some information on how you have dealt with this problem when writing cross-platform code?


Solution

  • There are several functions that are part of the POSIX specification, i.e. Linux and most other UNIX variants, that are not part of standard C. These include strdup, write, read, and others.

    The reasoning for the leading underscore is as follows, taken from the MSDN docs:

    The Universal C Run-Time Library (UCRT) supports most of the C standard library required for C++ conformance. It implements the C99 (ISO/IEC 9899:1999) library, with certain exceptions: The type-generic macros defined in , and strict type compatibility in . The UCRT also implements a large subset of the POSIX.1 (ISO/IEC 9945-1:1996, the POSIX System Application Program Interface) C library. However, it's not fully conformant to any specific POSIX standard. The UCRT also implements several Microsoft-specific functions and macros that aren't part of a standard.

    Functions specific to the Microsoft implementation of Visual C++ are found in the vcruntime library. Many of these functions are for internal use and can't be called by user code. Some are documented for use in debugging and implementation compatibility.

    The C++ standard reserves names that begin with an underscore in the global namespace to the implementation. Both the POSIX functions and Microsoft-specific runtime library functions are in the global namespace, but aren't part of the standard C runtime library. That's why the preferred Microsoft implementations of these functions have a leading underscore. For portability, the UCRT also supports the default names, but the Microsoft C++ compiler issues a deprecation warning when code that uses them is compiled. Only the default names are deprecated, not the functions themselves. To suppress the warning, define _CRT_NONSTDC_NO_WARNINGS before including any headers in code that uses the original POSIX names.

    I've handled that by having a #define that check if the program is being compiled for Windows, and if so create another #define to map the POSIX name to the Windows specific name. There are a few choices you can check, although probably the most reliable is _MSC_VER which is defined if MSVC is the compiler.

    #ifdef _MSC_VER
    #define strdup(p) _strdup(p)
    #endif