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