3

我正在将一个适用于 Ubuntu 8.04(gcc 版本 4.2.4)的程序移植到 10.04(gcc 版本 4.4.3)。我有以下代码:

#include <stdio.h>
#include <string.h>

int main(void) {
  char p[100] = "////abcd";
  char *t;

  /* Remove duplicate slashes, saving only one of them */
  while (t = strstr(p, "//"))
    strcpy(t, t + 1);

  printf("%s\n", p);

  return 0;
}

结果应该是/abcd,它与 gcc 4.2.4 相同。对于 4.4.3,输出为/accd.

您能否建议我更改代码,以使用两个版本的 gcc 提供正确的输出,并最好解释这里发生了什么。

提前致谢!

4

1 回答 1

7

你只是走运了。

strcpy文档中:

strcpy() 函数应将 s2 指向的字符串(包括终止的空字节)复制到 s1 指向的数组中。如果复制发生在重叠的对象之间,则行为未定义。

在您的情况下,字符串重叠,您的程序会调用未定义的行为。

它曾经工作但不再工作的一个可能原因是,它strcpy可能已经被 GCC 实现为内置memmove(即在这种情况下是安全的),但出于性能原因,这改为非安全版本。(这纯属猜测。)

要修复它,请使用memmove而不是strcpy, 类似于:

while (t = strstr(p, "//")) {
  memmove(t, t+1, strlen(t)); // strlen(t)'s bytes worth of data
                              // will cover the string bytes left
                              // and the \0 terminator
}

这不是非常有效,但它可以便携工作 -memmove必须处理重叠的内存区域。

于 2011-09-23T15:05:43.483 回答