为什么在使用正确的参数类型调用时此 strtok() 会失败?

Why does this strtok() fail when invoked with correct parameter types?

我已将我的 C 程序中的一个问题追溯到对 strtok() 的调用(为了记录,其签名是 char *strtok(char *str, const char *delim))。在尝试在一个非常简单的玩具程序中重现该问题时,我遇到了困难 - 我传递了所有正确的参数类型,但每次我尝试 运行 代码时都会出现总线错误。

程序如下:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
     char* tok;
     char* str = "www.example.com";
     const char* split = ".";

     tok = strtok(str, split);
     while(tok != NULL) {
         printf("%s\n", tok);
         tok = strtok(NULL, split);
     }
}

奇怪的是,我发现将 str 声明为数组 (char str[] = "www.example.com") 并将对 str 的引用传递给初始 strtok 调用 (tok = strtok(&str, split) ) 似乎工作正常。

我并不是真的担心这里的功能 - 使用数组的解决方案有效。我很好奇为什么使用指向 char 的指针的原始实现失败并抛出总线错误。

如果

 char* str = "www.example.com";
 /// some code
 tok = strtok(str, split);

您正在使用(指向)字符串文字 作为第一个参数。由于 strtok() 可能会尝试更改传递给它的第一个参数的内容,您将面临 undefined behaviour.

引用自man page

Be cautious when using these functions. If you do use them, note that:

These functions modify their first argument. [...]

关于尝试更改字符串文字,来自 C11,章节 §6.4.5

[...] If the program attempts to modify such an array, the behavior is undefined

OTOH,如果你创建一个数组,用字符串文字初始化它并将数组传递给 strtok(),这是非常好的,因为你的数组可以被你的程序修改。