I'm running OS X Sierra and trying to compile a c program that uses strcpy_s
, but my installed clang compiler is using the c99 standard, but from what I've read strcpy_s requires c11.
Here's the code I'm trying to compile
#include#include #include int main(void) { char source[] = "Test string"; char destination[50]; if(strcpy_s(destination, sizeof(destination), source)) printf("string copied - %s",destination); return 0; }
And here's the command I'm using to compile
$ clang copytest.c -o copytest copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration] if(strcpy_s(copied_string, sizeof(copied_string), source)) ^ 1 warning generated. Undefined symbols for architecture x86_64: "_strcpy_s", referenced from: _main in copytest-e1e05a.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried compiling with the standard flag...
clang -std=c11 copytest.c -o copytest
but I get the same exact "invalid in c99" warning. I've also tried compiling with gcc instead, and I still get the same c99 warning.
I tried upgrading via homebrew which shows the following
Warning: gcc 9.2.0 is already installed and up-to-date
I have clang version 9.0.0
$ clang -v Apple LLVM version 9.0.0 (clang-900.0.39.2)
My xcode version is Xcode 9.2, which from everything I've read should come with c11 support.
Am I doing something wrong with the compiling, is my code itself incorrect? This is the only similar question I found on here, but it didn't even have an answer. Thanks
The _s
functions are an optional component of the 2011 C standard (Annex K), and, to the best of my knowledge, they have never been implemented as an integrated part of any C library. Portable code cannot rely on their availability. (Microsoft's C compilers for Windows implement an overlapping set of functions with the same names but different semantics (and sometimes even a different argument list), and at least one bolt-on implementation does exist. See this old answer, and the much longer question and answer it links to, for more detail.)
Also, the _s
functions do not solve the problem that they were intended to solve (unsafe string handling); it is necessary to put actual thought into a proper fix for each use of strcpy
, instead of globally search-and-replacing strcpy
with strcpy_s
, etc., as was the hope of the authors of Annex K. If you do put appropriate amounts of thought into a proper fix, you won't need any of the _s
functions to implement it. For instance, here's a fixed version of your example program:
#include#include #include int main(void) { char source[] = "Test string"; char destination[50]; size_t srclen = strlen(source); if (srclen + 1 > sizeof destination) { fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n", sizeof destination, srclen + 1); return 1; } else { memcpy(destination, source, srclen + 1); printf("string copied - %s\n", destination); return 0; } }
And here's an even better version:
#define _XOPEN_SOURCE 700 #include#include int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: ./test 'message of arbitrary length'\n"); return 1; } char *destination = strdup(argv[1]); if (!destination) { perror("strdup"); return 1; } printf("string copied - '%s'\n", destination); free(destination); return 0; }
Therefore: Never use any of the _s
functions. If you need to write a program that compiles on Windows with no warnings, put #define _CRT_SECURE_NO_WARNINGS 1
at the top of each file to make MSVC stop giving you bad advice.