这是我的程序的一个片段
#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;
}
strtok_r
manual
strtok_r():_POSIX_C_源
/|BSD|u源| | SVID|u源
如果我把程序编译成
cc t.c -std=c99
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);
^
有什么比这更糟的吗
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
相应的输出
Okay
so
lets
split
this
and
see
how
it
works
关于为什么会有这种行为有什么线索吗?
所以这似乎是
strtok_r
glibc的特性测试宏要求(参见
功能测试宏(7):
strtok_r(): _POSIX_C_SOURCE
|| _BSD_SOURCE || _SVID_SOURCE
feature_test_macros
,必须进行以下宏定义之一
在包含任何头文件之前:
#define _BSD_SOURCE
#define _XOPEN_SOURCE
Alternatively, equivalent definitions can be included in the compilaâ
tion command:
cc -D_BSD_SOURCE
cc -D_XOPEN_SOURCE # Or any value < 500
因此,正如@someprogrammer dude指出的,包含这些宏定义是必须的,否则它将导致UB,这最终就是这里发生的事情。