我正在将一个与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来提供正确的输出代码,并且最好解释一下这里发生了什么。
提前致谢!
答案 0 :(得分: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
必须处理重叠的内存区域。