C 与strtok_r I'的故障;我这里遗漏了什么

C 与strtok_r I'的故障;我这里遗漏了什么,c,C,这是我的程序的一个片段 #include <stdio.h> #include <string.h> void something_wrong_really(char *str) { char *savedptr = NULL; char *delim = " "; for ( char *p = str ; ; p = NULL) { char *token = strtok_r(

这是我的程序的一个片段

#include <stdio.h>
#include <string.h>
void  something_wrong_really(char *str)
{
        char *savedptr = NULL;
        char *delim    = " ";

        for ( char *p = str ; ; p = NULL) {
                char *token = strtok_r(p, delim, &savedptr);
                if (token == NULL)
                        break;
                printf(" %s\n", token);
        }
}

int main(void) {
    char str[] = "Okay so lets split this and see how it works";
    something_wrong_really(str);
    return 0;
}
我最终得到了警告

t.c: In function 'something_wrong_really':
t.c:10:3: warning: implicit declaration of function 'strtok_r' [-Wimplicit-function-declaration]
   char *token = strtok_r(p, delim, &savedptr);
   ^
t.c:10:17: warning: initialization makes pointer from integer without a cast [enabled by default]
   char *token = strtok_r(p, delim, &savedptr);
                 ^
执行it时最糟糕的是什么
segfaults

./a.out
Segmentation fault
对应轨迹

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a5af19 in vfprintf () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64
(gdb) bt
#0  0x00007ffff7a5af19 in vfprintf () from /lib64/libc.so.6
#1  0x00007ffff7a61339 in printf () from /lib64/libc.so.6
#2  0x00000000004005e2 in something_wrong_really (str=0x7fffffffe0a0 "Okay") at t.c:13
#3  0x0000000000400653 in main () at t.c:19
(gdb)
另一方面,当启用其中一个标志时,事情似乎运行得非常好

 _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
相应输出

# cc t.c -std=c99 -D_BSD_SOURCE
#
#
# ./a.out
 Okay
 so
 lets
 split
 this
 and
 see
 how
 it
 works
#
有没有关于为什么会有这种行为的提示


因此,这似乎是手册中的片段

glibc的特性测试宏要求(参见 功能测试宏(7)):

strtok_r():_POSIX_C_SOURCE

||/*Glibc versions如果未使用正确的启用宏(
\u POSIX\u C_SOURCE
根据),则不会自动声明该函数。这意味着编译器必须推导参数类型,更重要的是返回类型将自动为
int
(如第二条警告消息中所述)

如果参数类型或返回类型错误,那么该调用将导致,并且很可能会崩溃

通过添加正确的宏,函数将在头文件中正确声明,并且将使用正确的参数类型和返回值



这里的问题可能是不匹配的返回类型。在64位系统上,指针(如
char*
)的宽度为64位,而
int
的宽度通常只有32位。这种大小不匹配会导致许多指针出错,试图使用它们是分段错误的一个重要来源。

首先,您引用的手册明确指出您需要
#include
,但这会阻止编译器发出警告,而不是segfault.dumped full source includes;-)通常,“隐式函数声明”警告应视为错误。最新的编辑对我来说工作正常。请注意,当设置为在严格标准模式下编译时,gcc之类的编译器通常拒绝在标准头中包含非标准垃圾<代码>strtok_r
不是标准的,但是POSIX垃圾坚持函数应该放在标准库头中——这直接违反了C标准。因此,由于POSIX的缺陷,可能无法编译您的程序。我建议您推出自己的线程安全strtok,这样做相当简单。POSIX中的许多设计错误似乎不太可能得到修复,因此尽可能避免它。这似乎是解决方案,但我并不期待没有定义编译选项的SEGFULT-(这对我来说似乎很奇怪。@u_uuu未定义的行为有时会导致崩溃。@u_uu我认为这与Somme程序员dude早些时候给我的评论有关。你除了要包含标题外,还要定义你的源代码是否与posix兼容。如果编译器没有看到Arumgins并提供错误的参数,就不能o函数,坏事情发生。
# cc t.c -std=c99 -D_BSD_SOURCE
#
#
# ./a.out
 Okay
 so
 lets
 split
 this
 and
 see
 how
 it
 works
#
   strtok_r(): _POSIX_C_SOURCE
       || /* Glibc versions <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE
       #define _BSD_SOURCE
       #define _XOPEN_SOURCE        /* or any value < 500 */

   Alternatively, equivalent definitions can be included in the compila‐
   tion command:

       cc -D_BSD_SOURCE
       cc -D_XOPEN_SOURCE           # Or any value < 500