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

发布于 2024-12-06 16:58:48 字数 516 浏览 1 评论 0原文

我正在将一个适用于 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 提供正确的输出,并且最好解释一下这里发生的情况。

提前致谢!

I'm porting a program that works with Ubuntu 8.04 (gcc version 4.2.4) to 10.04 (gcc version 4.4.3). I have the following code:

#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;
}

The result should be /abcd, which it is with gcc 4.2.4. With 4.4.3, the output is /accd.

Can you suggest me a code change that will give the correct output using both versions of gcc, and preferrably explain what is going on here.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

千纸鹤 2024-12-13 16:58:48

你只是很幸运。

来自 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 必须处理重叠内存地区。

You've just been lucky.

From the strcpy documentation:

The strcpy() function shall copy the string pointed to by s2 (including the terminating null byte) into the array pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

The strings overlap in your case, your program invokes undefined behavior.

A possible reason why it used to work but no longer does is that strcpy could have been implemented as a builtin by GCC like memmove (i.e. safe in this situation), but this changed to a non-safe version for performance reasons. (This is pure speculation.)

To fix it, use memmove rather than strcpy, with something like:

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
}

That's not terribly efficient, but it will work portably - memmove has to handle overlapping memory areas.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文