C:将strtok令牌分配给char * Segfault
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C:将strtok令牌分配给char * Segfault相关的知识,希望对你有一定的参考价值。
为什么我会使用以下代码获得段错误?
#include <stdio.h>
int main()
{
char * tmp = "0.1";
char * first = strtok(tmp, ".");
return 0;
}
编辑:
#include <stdio.h>
int main()
{
char tmp[] = "0.1";
char *first = strtok(tmp, ".");
char *second = strtok(tmp, "."); // Yes, should be NULL
printf("%s
", first);
printf("Hello World
");
return 0;
}
可以在这里的在线gdb上复制段错误:https://www.onlinegdb.com/online_c_compiler
你的第一个代码的问题是tmp
指向一个字符串文字,这是只读的。当strtok
尝试修改字符串时,它会崩溃。
您的第二个代码的问题是缺少包括:
#include <string.h>
这个缺少的标题意味着strtok
在您的程序中未声明。 C编译器假定所有未声明的函数都返回int
。对于返回strtok
的char *
来说,情况并非如此。您的示例中可能导致崩溃的原因是代码在64位计算机上运行,其中指针为8字节宽,但int
仅为4字节。这会弄乱strtok
的返回值,所以first
是一个垃圾指针(当printf
尝试使用它时崩溃)。
您可以通过这样做来自己确认
char *first = strtok(tmp, ".");
printf("%p %p
", (void *)tmp, (void *)first);
为tmp
和first
打印的地址应该是相同的(如果你是#include <string.h>
,那就是它们)。
有趣的是,gcc可以警告你这些问题:
main.c: In function 'main':
main.c:6:19: warning: implicit declaration of function 'strtok' [-Wimplicit-function-declaration]
char *first = strtok(tmp, ".");
^
main.c:6:19: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
main.c:7:20: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
char *second = strtok(tmp, "."); // Yes, should be NULL
^
...并且onlinegdb将向您显示这些警告,但仅限于编译失败!
因此,要在onlinegdb上查看编译器警告,您必须向代码添加一个硬错误(例如,将@
放在文件的最后一行)。
函数strtok
的行为是这样的:
- 接受字符串
str
或NULL以及一串分隔符字符。 - 然后strtok函数开始处理给定的字符串
str
,其中它逐字符地读取字符串,直到它遇到所提供的分隔符字符中存在的字符。 - 如果到达分隔符字符串之前遇到的字符数> 0,则用' n'替换分隔符字符,并返回指向此迭代中第一个字符的指针,该字符不是分隔符。
- 否则,如果到达分隔符字符串之前遇到的字符数是== 0,则继续迭代字符串的其余部分,而不用' n'替换此分隔符。
我已经创建了一些代码片段,可以帮助您更好地理解函数的性质,https://ideone.com/6NCcrR和https://ideone.com/KVI5n4(
现在回答你的问题,包括
string.h
标题和设置char tmp[] = "0.1";
应该解决你的问题。
使用char * tmp = "0.1";
,tmp
指向无法修改的字符串文字,strtok
尝试通过用.
替换' '
来修改字符串。
避免使用segfault的另一种方法是使用strchr
查找点和精度字段来打印有限数量的字符。子字符串也可以复制到其他变量。
#include <stdio.h>
#include <string.h>
int main ( void) {
char * tmp = "0.1";
char * first = strchr(tmp, '.');
char * second = first + 1;
if ( first) {
printf ( "%.*s
", first - tmp, tmp);
printf ( "%s
", second);
}
printf ( "Hello World
");
return 0;
}
tmp不是字符串文字,因为很少有答案或评论指出。
char * tmp =“0.1”这是一个字符串文字。
char tmp [] =“0.1”是一个字符数组,可以对它们执行所有数组操作。
出现段错误是因为未找到strtok的函数声明,因为string.h未包含在内,并且gcc或其他c编译器默认将返回类型隐式声明为int。
现在取决于平台,如果int size是4字节并且指针大小分别是8字节,则整数大小可以变化
char * first =(int)strtok(tmp,“。”);
截断发生在strtok返回的指针地址上,然后在打印时,您将取消引用首先包含的地址值,该地址值可能是一个超出范围的内存区域,从而导致分段错误或未定义的行为。
如果你可以将strtok的输出类型转换为8字节的类型(在我的情况下很长),那么就不会有段错误,尽管这不是一个干净的方法。
包括适当的头文件以避免未定义的行为。
以上是关于C:将strtok令牌分配给char * Segfault的主要内容,如果未能解决你的问题,请参考以下文章