首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >strtok分段错误

strtok分段错误
EN

Stack Overflow用户
提问于 2012-01-22 08:00:56
回答 8查看 39.2K关注 0票数 17

我正在尝试理解为什么下面的代码片段会给出一个分段错误:

代码语言:javascript
复制
void tokenize(char* line)
{
   char* cmd = strtok(line," ");

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

int main(void)
{
   tokenize("this is a test");
}

我知道strtok()实际上不会对字符串文字进行标记化,但在本例中,line直接指向字符串"this is a test",该字符串在内部是一个char数组。是否可以在不将line复制到数组中的情况下对其进行标记化?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-01-22 08:22:39

问题是您正在尝试修改字符串文字。这样做会导致您的程序的行为是未定义的。

说不允许修改字符串文字是过于简单化了。说字符串字面值是const是不正确的,其实不然。

警告:后面跟着分题。

字符串文字"this is a test"的表达式类型为char[15] (14表示长度,1表示终止'\0')。在大多数上下文中,包括这个表达式,这样的表达式被隐式转换为指向数组第一个元素的指针,类型为char*

试图修改string文本引用的数组的行为是未定义的--不是因为它是const (它不是),而是因为C标准明确规定它是未定义的。

一些编译器可能会允许您逃脱这一点。您的代码实际上可能会修改与文本相对应的静态数组(这可能会在以后造成很大的混乱)。

不过,大多数现代编译器都会将数组存储在只读内存中--不是物理ROM,而是存储在受虚拟内存系统保护的内存区域中。尝试修改这种内存的结果通常是分段错误和程序崩溃。

那么为什么字符串文字不是const呢?既然您真的不应该尝试修改它们,那么这样做肯定是有意义的--而且C++确实将字符串字面值设为const。原因是历史的。在1989年的ANSI标准引入const关键字之前,它并不存在(尽管在此之前,一些编译器可能已经实现了它)。因此,ANSI之前的程序可能如下所示:

代码语言:javascript
复制
#include <stdio.h>

print_string(s)
char *s;
{
    printf("%s\n", s);
}

main()
{
    print_string("Hello, world");
}

print_string不允许修改s所指向的字符串,这一事实是无法强制执行的。在ANSI中使用const会破坏现有的代码,这是ANSI委员会极力避免的。从那时起,就没有一个很好的机会对语言进行这样的更改。( C++的设计者,主要是Bjarne Stroustrup,并不关心与C的向后兼容性。)

票数 25
EN

Stack Overflow用户

发布于 2012-01-22 08:04:41

Strok修改了它的第一个参数,以便对其进行标记化。因此,您不能向它传递文字字符串,因为它的类型是const char *,并且不能修改,因此出现了未定义的行为。您必须将字符串文字复制到可修改的char数组中。

票数 5
EN

Stack Overflow用户

发布于 2012-01-22 08:02:45

正如您所说的,您不能修改字符串文字,而这正是strtok所做的。你必须这样做

代码语言:javascript
复制
char str[] = "this is a test";
tokenize(str);

这将创建数组str并使用this is a test\0对其进行初始化,然后将指向该数组的指针传递给tokenize

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8957829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档