[英]C - Unexpected Segmentation Fault on strtok(…)
我正在使用库的strtok(...),它似乎工作正常,直到结束条件,它导致分段错误和程序崩溃。 API声称strtok(...)将在没有找到更多令牌时输出NULL,这意味着,我想,你必须捕获这个NULL才能终止你使用strtok运行的任何循环( ...)。 我需要做什么才能捕获此NULL以防止程序崩溃? 我想象允许使用NULL作为终止条件。
我准备了一个SSCCE供你观察这种行为。 我需要strtok(...)来处理我正在编写的更大的软件,并且我得到完全相同的分段行为。 命令行的输出显示在此代码插图下方(是的,我知道您使用<...>来封装库,但是我很难获得此帖子来显示代码库)。 我在Windows 8操作系统上使用gcc 4.5.3版本,下面显示了我想象的两种不同风格,我可以尝试在循环中捕获NULL。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
main(){
char* from = "12.34.56.78";
char * ch = ".";
char * token = strtok(from, ch);
printf("%s\n",token);
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token);
}
printf("Broke out of loop!");
while(strcmp(token, 0) != 0){
printf("%s\n",token);
token = strtok(NULL, ch);
}
}
############ OUTPUT: ############ $ ./test 12 34 56 78 Segmentation fault (core dumped)
strtok
修改了它的第一个参数。 您从只读内存传递一个字符串,当strtok
尝试更改它时发生segfault。 尝试改变:
char* from = "12.34.56.78";
至
char from[] = "12.34.56.78";
你首先检查token
是否不等于NULL(当它是,它突破了while
循环)。 然后你比较token
,这是一个NULL
与常数NUMBER? 这里: strcmp(token, 0)
当strcmp
需要2个字符串时,你提供一个数字。 strcmp
将尝试在第0个地址(或NULL)获取字符串,从而为您提供分段错误。
while(strcmp(token, 0) != 0){
token = strtok(NULL, ch);
printf("%s\n",token);
}
此代码也应如下所示:
更改
char * token = strtok(from, ch);
printf("%s\n",token);
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token);
}
至
char * token = strtok(from, ch);
printf("%s\n",token);
while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, ch);
}
这是个问题:
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token);
}
你正在检查NULL,但是再次调用strtok
而不是在那之后但是在打印之前检查。
代码还有其他问题,但我怀疑这就是它崩溃的原因。
问题是即使你在strtok()
返回NULL
时终止循环,你首先尝试打印NULL
:
while(token != NULL){
token = strtok(NULL, ch);
printf("%s\n", token); // not good when token is NULL
}
事实证明,除了这个例子之外,在这个例子中还有几个机会用于segfaults,正如其他答案所指出的那样。
这是处理示例标记化的一种方法:
char from[] = "12.34.56.78";
char * ch = ".";
char * token = strtok(from, ch);
while (token != NULL){
printf("%s\n", token);
token = strtok(NULL, ch);
}
如果代码的目的只是打印以'。'分隔的元素,则只更改char声明并在打印令牌之前检查其值是否为NULL!
main(){
char from[] = "12.34.56.78.100.101";
char * ch = ".";
char * token = strtok(from, ch);
//printf("%s\n",token);
while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, ch);
}
}
OUTPUT
./test1 12 12 34 56 78 100 101
您有内存访问错误和逻辑错误。 我只会解决导致程序崩溃的内存访问错误。
strtok
修改了它的第一个参数。 由于传入字符串文字,因此无法修改字符串(字符串文字不可修改。)
这是一个可能的修复, from
一个可修改的字符串数组定义:
char from[] = "12.34.56.78";
因为strtok
修改了传入其中的字符串,所以在第二个while循环中不能再次处理该字符串。 您实际上是将NULL传入strcmp
函数。 可能的解决方法是每次要使用strtok
时将from
数组复制到另一个缓冲区。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.