strncpy()分段错误:可疑的strtok()操作?
我正在写一个程序,从用户那里提取行并解析它们,作为家庭作业。 我受限于一定的内存量,因此我只能使用下面使用的变量 我的代码有一个分段错误,使用gdb发现它源于下面的strncpy()函数调用。我能看到发生这种情况的唯一原因是str有问题,这是由我使用strtok()引起的。如果有人能指出我是如何错误地使用strtok()的,或者是一种不添加任何变量而通过空格解析字符串的替代方法,我将非常感激 字符串的格式为“00 COMMAND 0”,我试图将最后一位放入数组,同时保留该命令以供以后计算。命令的长度从3到4个字符不等strncpy()分段错误:可疑的strtok()操作?,c,string,segmentation-fault,C,String,Segmentation Fault,我正在写一个程序,从用户那里提取行并解析它们,作为家庭作业。 我受限于一定的内存量,因此我只能使用下面使用的变量 我的代码有一个分段错误,使用gdb发现它源于下面的strncpy()函数调用。我能看到发生这种情况的唯一原因是str有问题,这是由我使用strtok()引起的。如果有人能指出我是如何错误地使用strtok()的,或者是一种不添加任何变量而通过空格解析字符串的替代方法,我将非常感激 字符串的格式为“00 COMMAND 0”,我试图将最后一位放入数组,同时保留该命令以供以后计算。命令的
char str[11];
*count = 0;
while( scanf( "%[^\n]%*c", str ) == 1 )
{
printf( "\n%s\n", str );
strtok( str, " " );
strtok( NULL, " " );
memory[*count] = atoi( strtok( NULL, " " ) );
strtok( str, " " );
strncpy( str, strtok( NULL, " " ), sizeof( str ) );
strtok通过在标记末尾添加“\0”字符来更改str。因此,第二次使用str作为参数调用strtok时,它只会看到字符串的“00”部分。 最简单的修复方法是通过标记化第一次保存命令部分:
strtok( str, " " );
strncpy( str, strtok( NULL, " " ), sizeof( str ) );
memory[*count] = atoi( strtok( NULL, " " ) );
当然,您还应该检查strtok的返回值,以确保没有传递错误的输入
编辑-oops。我没有意识到您想要将命令存储回str。将命令部分复制回str应该是安全的,因为它必须比第一个参数+命令短。不过,这看起来确实有点可疑。最好为命令使用另一个指针变量。它只有另外4-8个字节(取决于您的系统)
在我看来,要做的第一件事是从
strtok()
捕获并打印返回值,或者在您期望非null返回时检查它们是否为null
鉴于守则的第二部分:
strtok(str, " ");
strncpy(str, strtok(NULL, " "), sizeof(str));
您正在使用strncpy()
在字符串本身上复制一段str
。这是未定义的行为:
如果复制发生在重叠的对象之间,则行为未定义
当您调用未定义的行为时,任何事情都可能发生。只需将第二个令牌指针保存到'str'。不需要复制
printf( "\n%s\n", str );
strtok( str, " " ); /* apparently you don't care about this token */
str = strtok( NULL, " " ); /* 'str' now points to COMMAND */
memory[*count] = atoi( strtok( NULL, " " ) );
不管您在做什么,
atoi(strtok
总是有风险的,因为strtok
可能返回NULL。在传递到atoi
(或strncpy
)之前检查返回值。还要注意,如果源字符串足够长,则strncpy
不会为null并终止其缓冲区;因此,如果您以后想将str
作为字符串访问,则明智的做法是将'\0'
放在末尾,或者更好的做法是,完全避免strncpy
。我知道,我会完全避免strncpy当然有问题,但是我需要使用的编译器设置不支持其他选项。谢谢你的回答。谢谢你的回答,但是除非我弄错了,否则我们不能这样分配数组,这就是为什么我一开始就在与strncpy打交道。
printf( "\n%s\n", str );
strtok( str, " " ); /* apparently you don't care about this token */
str = strtok( NULL, " " ); /* 'str' now points to COMMAND */
memory[*count] = atoi( strtok( NULL, " " ) );