【问题标题】:strncpy() segmentation fault: shady strtok() manipulations?strncpy() 分段错误:可疑的 strtok() 操作?
【发布时间】:2014-03-21 04:45:02
【问题描述】:

我正在编写一个程序,该程序从用户那里获取行并解析它们以完成家庭作业。 我受限于一定数量的内存,所以我下面使用的变量是我唯一可以使用的变量。

我的代码出现分段错误,使用 gdb 发现它源自下面的 strncpy() 函数调用。我能看到发生这种情况的唯一原因是 str 有问题,这是由于我使用 strtok() 引起的。如果有人能指出我如何错误地使用 strtok() 或另一种通过空格解析字符串而不添加任何变量的方法,我将不胜感激。

字符串的格式为“00 COMMAND 0”,我试图将最后一位放入数组中,同时保留 COMMAND 以供以后计算。 COMMAND 的长度从 3 到 4 个字符不等。

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 ) );

【问题讨论】:

  • 不管你在做什么,atoi( strtok 总是有风险的,因为strtok 可能返回 NULL。在传递给atoi(或strncpy)之前检查返回值。
  • 还要注意strncpy 不会在源字符串长到足以填满它的缓冲区时终止它的缓冲区;因此,如果您以后想以字符串的形式访问str,那么明智的做法是在末尾加上'\0',或者更好的是,完全避免strncpy
  • 我会完全避免使用 strncpy,因为我知道它的问题,但我需要使用的编译器设置不支持替代方案。

标签: c string segmentation-fault


【解决方案1】:

strtok 通过在标记末尾添加 '\0' 字符来更改 str。所以第二次以str作为参数调用strtok,它只会看到字符串的“00”部分。 最简单的解决方法是第一次通过标记化保存命令部分:

strtok( str, " " );
strncpy( str, strtok( NULL, " " ), sizeof( str ) );
memory[*count] = atoi( strtok( NULL, " " ) );

当然,您还应该检查 strtok 的返回值,以确保您没有收到错误的输入。

编辑 - 哎呀。我没有意识到您想将命令存储回 str.将命令部分复制回 str 应该是安全的,因为它必须比第一个参数 + 命令短。不过它看起来确实有点狡猾。您最好为命令使用另一个指针变量。它只是另外 4-8 个字节(取决于您的系统)。

char *command;
strtok( str, " " );
command = strtok( NULL, " " );
memory[*count] = atoi( strtok( NULL, " " ) );

【讨论】:

  • 感谢您的回答。
【解决方案2】:

在我看来,首先要做的是捕获并打印来自strtok() 的返回值,或者在您期待非空返回时检查它们是否不为空。

鉴于代码的第二部分:

strtok(str, " ");
strncpy(str, strtok(NULL, " "), sizeof(str));

您正在使用strncpy() 将字符串str 的一部分复制到自身之上。那是未定义的行为:

如果复制发生在重叠的对象之间,则行为未定义。

当您调用未定义的行为时,任何事情都可能发生。

【讨论】:

    【解决方案3】:

    只需将第二个标记指针保存到“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, " " ) );
    

    【讨论】:

    • 感谢您的回复,但除非我弄错了,否则我们不能分配给这样的数组,这就是我一开始就使用 strncpy 的原因。
    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多