2

I'm trying to use the C11 function strtok_s, which is supposed to be defined in <string.h>, but clang is giving me a linking error when I try to use it. Compiling this program:

#include <string.h>

int main() {
    char * buffer;
    char * state;
    rsize_t strmax = 0;
    char * fpl = strtok_s(buffer, &strmax, "\n", &state);
}

Gives me this error:

repro.c:7:15: warning: implicit declaration of function 'strtok_s' is invalid in
  C99 [-Wimplicit-function-declaration]
    char * fpl = strtok_s(buffer, &strmax, "\n", &state);
                 ^
repro.c:7:9: warning: incompatible integer to pointer conversion initializing
  'char *' with an expression of type 'int' [-Wint-conversion]
    char * fpl = strtok_s(buffer, &strmax, "\n", &state);
           ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 warnings generated.
Undefined symbols for architecture x86_64:
  "_strtok_s", referenced from:
  _main in repro-3dcfc9.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'm using clang 8.1.0 on OS X 10.12.6. What am I doing wrong?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
hiy
  • 449
  • 5
  • 15
  • Buffer is not set to point to any memory that the application owns. The result of the call to `strtok_s()` is undefined behavior and could lead to a seg fault event. Suggest 1) set the value in `Buffer` to point to a character array that the application owns. 2) Initialize the character array to a known string. – user3629249 Apr 15 '18 at 16:37
  • See also [Do you use the TR-24731 "safe" functions?](https://stackoverflow.com/questions/372980/do-you-use-the-tr-24731-safe-functions) — and note that the `strtok_s()` defined in Annex K of the C11 standard does not match either `strtok_s()` as implemented on Windows or `strtok_r()` as implemented for POSIX systems — though the Windows `strtok_s()` and POSIX `strtok_r()` are essentially equivalent to each other. – Jonathan Leffler Jun 04 '18 at 17:59

2 Answers2

5

strtok_s is optional in C11; honestly only Windows implements it. Use strtok_r on POSIX systems.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • 3
    And Windows doesn't even implement the bounds-checking interfaces in quite the same way that C11's Annex K describes (e.g. there is no `set_constraint_handler_s` function; instead, you must use the MSVC-specific `_set_invalid_parameter_handler` function, which takes a completely different set of arguments). –  Apr 14 '18 at 14:42
  • it is weird to see `strtok_s()` listed in [C17 standard](https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf) but you still cannot use it even you already define `__STDC_WANT_LIB_EXT1__` prior to including `` , I work with Linux so `strtok_r` is probably the only alternative :/ – Ham Feb 09 '22 at 15:41
3

http://en.cppreference.com/w/c/string/byte/strtok:

As all bounds-checked functions, strtok_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined by the implementation and if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including string.h.

melpomene
  • 84,125
  • 8
  • 85
  • 148