strstr:使用不同版本的gcc进行不同的行为

Joh*_*han 3 c gcc strstr

我正在将一个与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;
}
Run Code Online (Sandbox Code Playgroud)

结果应该/abcd是gcc 4.2.4.使用4.4.3,输出为/accd.

你能否建议我使用两种版本的gcc来提供正确的输出代码,并且最好解释一下这里发生了什么.

提前致谢!

Mat*_*Mat 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
}
Run Code Online (Sandbox Code Playgroud)

这不是非常有效,但它可以移植 - memmove必须处理重叠的内存区域.

  • 在使用gcc 4.4.3进行编译之前,Johan是不吉利的** (3认同)