【问题标题】:strcat() crashes if using same array as both parameters如果使用相同的数组作为两个参数,strcat() 会崩溃
【发布时间】:2014-03-28 15:04:46
【问题描述】:
char r[40];
strcpy(r,"abcdef");
strcat(r,r);

我的程序在第三行崩溃了?

替换 strcat(r,r);通过 strcat(r,"abcdef");虽然工作正常....为什么会这样?

【问题讨论】:

  • 思考如何自己实现strcat() 可能是一个很好的学习体验(这是一个非常简单的函数)。然后检查您的实现是否处理自连接以及您可能需要做什么才能使其能够处理它。然后考虑是否每个打电话给strcpy()的人都应该支付支持诸如自连接这样可能很少使用的功能的成本。

标签: c c-strings strcat


【解决方案1】:

根据strcat(3)

strcat() 函数将 src 字符串附加到 dest 字符串,覆盖 dest 末尾的终止空字节 ('\0'),然后添加终止空字节。 字符串不能重叠,且dest字符串必须有足够的空间存放结果。

【讨论】:

    【解决方案2】:

    迟到的答案。只是想添加一点“图形”解释。

    如果您考虑如何实现strcat,它会在源字符串的第一个字符处初始化一个指针,然后逐个字符地遍历源,直到它到达其空字节。但由于源字符串和目的字符串相同,可能会出现以下情况。

    记忆是这样开始的:

    a b c d e f \0
    

    source (s) 和 dest (d) 指针都指向函数入口的a。 dest 指针移动到末尾,我们准备复制

    s           d 
    a b c d e f \0
    
      s           d
    a b c d e f a
    
        s           d
    a b c d e f a b
    
          s           d
    a b c d e f a b c
    
            s           d
    a b c d e f a b c d
    
              s           d
    a b c d e f a b c d e
    
                s           d
    a b c d e f a b c d e f
    
                  s           d
    a b c d e f a b c d e f a
    

    您可以看到源指针不会到达其终止的空字节,因为它在一开始就被破坏了。最终我们会用完这里的空间。

    因此,由于这是一种可能的情况,strcat 的定义不允许两个字符串重叠。这样实现就可以免费使用基本实现了。

    【讨论】:

      【解决方案3】:

      strcat() 从输入读取并将其复制到输出,直到在输入中找到 \0 终止符。通过为输入和输出指定相同的数组,您可以在读取输入时修改输入。

      您必须检查编译器对 strcat() 的特定实现,但如果您跟踪如下的简单实现,您应该会明白为什么您的代码会在一段时间后崩溃:

      char *strcat(char *dest, const char *src )
      {
          char *ret = dest;
          if (dest && src)
          {
              while (*dest != 0)
                  ++dest;
              while (*str != 0)
                  *dest++ = *src++;
              *dest = 0;
          }
          return ret;
      }
      

      while (*dest != 0) 循环之后,dest 现在指向输入的\0 终止符。 while (*str != 0) 循环的第一次迭代然后用a 替换该终止符,从而导致循环不再在它应该停止的地方停止。最终,循环将超出输入的边界并开始读取周围的内存,如果在命中无效内存之前没有找到另一个 \0 字节,它将最终崩溃。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        • 2015-03-08
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 1970-01-01
        • 2015-03-28
        相关资源
        最近更新 更多