Valgrind 警告:我应该认真对待它吗

发布于 2024-10-14 20:07:26 字数 394 浏览 14 评论 0原文

背景: 我有一个模仿 fgets(character, 2, fp) 的小例程,只不过它从字符串而不是流中获取字符。 newBuff 是作为参数传递的动态分配的字符串,字符被声明为 char character[2]。

例程:

character[0] = newBuff[0];

character[1] = '\0';

strcpy(newBuff, newBuff+1);

strcpy 会在读取每个字符时复制丢失的信息。

问题:Valgrind 确实警告我 本活动“来源和目的地 strcpy 中的重叠(0x419b818, 0x419b819)”。

我应该担心这个警告吗?

Background:
I have a small routine that mimics fgets(character, 2, fp) except it takes a character from a string instead of a stream. newBuff is dynamically allocated string passed as a parameter and character is declared as char character[2].

Routine:

character[0] = newBuff[0];

character[1] = '\0';

strcpy(newBuff, newBuff+1);

The strcpy replicates the loss of information as each character is read from it.

Problem: Valgrind does warns me about
this activity, "Source and destination
overlap in strcpy(0x419b818,
0x419b819)".

Should I worry about this warning?

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

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

发布评论

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

评论(6

看透却不说透 2024-10-21 20:07:26

标准可能没有指定这些缓冲区重叠时会发生什么。所以,是的,valgrind 对此的抱怨是正确的。

实际上,您很可能会发现您的 strcpy 按从左到右的顺序复制(例如while (*dst++ = *src++);< /code>) 并且这不是问题。但它仍然不正确,并且在与其他 C 库一起运行时可能会出现问题。

一种标准正确的编写方法是:

memmove(newBuff, newBuff+1, strlen(newBuff));

因为 memmove 被定义为处理重叠。 (虽然在这里你最终会遍历字符串两次,一次检查长度,一次复制。我还采取了捷径,因为 strlen(newBuff) 应该等于 strlen(newBuff+1 )+1,这是我最初写的。)

Probably the standard does not specify what happens when these buffers overlap. So yes, valgrind is right to complain about this.

In practical terms you will most likely find that your strcpy copies in order from left-to-right (eg. while (*dst++ = *src++);) and that it's not an issue. But it it still incorrect and may have issues when running with other C libraries.

One standards-correct way to write this would be:

memmove(newBuff, newBuff+1, strlen(newBuff));

Because memmove is defined to handle overlap. (Although here you would end up traversing the string twice, once to check the length and once to copy. I also took a shortcut, since strlen(newBuff) should equal strlen(newBuff+1)+1, which is what I originally wrote.)

动次打次papapa 2024-10-21 20:07:26

是的,您还应该担心您的函数具有病态的糟糕性能(对于本应为 O(n) 的任务,O(n^2))。每次读取一个字符时,将字符串的全部内容向后移动一个字符,这会浪费大量时间。相反,您应该只保留指向当前位置的指针并递增该指针。

如果您发现自己需要 memmove 或等效项(在重叠的缓冲区之间进行复制)几乎总是,则表明存在设计缺陷。通常,这不仅仅是实现中的缺陷,而且是界面中的缺陷。

Yes, and you should also worry that your function has pathologically bad performance (O(n^2) for a task that should be O(n)). Moving the entire contents of the string back by a character every time you read a character is a huge waste of time. Instead you should just keep a pointer to the current position and increment that pointer.

Situations where you find yourself needing memmove or the equivalent (copying between buffers that overlap) almost always indicate a design flaw. Often it's not just a flaw in the implementation but in the interface.

暖树树初阳… 2024-10-21 20:07:26

是的 - 仅当源和目标不重叠时才定义 strcpy 的行为。您可以考虑将 strlenmemmove 组合起来。

Yes -- the behavior of strcpy is only defined if the source and dest don't overlap. You might consider a combination of strlen and memmove instead.

放血 2024-10-21 20:07:26

是的,你应该担心。 C 标准规定 strcpy 的行为是 当源对象和目标对象重叠时,未定义。未定义的行为意味着它有时可能会起作用,也可能会失败,或者它可能看起来成功,但在程序的其他地方却显示出失败。

Yes, you should worry. The C standard states that the behavior of strcpy is undefined when the source and destination objects overlap. Undefined behavior means it may work sometimes, or it may fail, or it may appear to succeed but manifest failure elsewhere in the program.

原来是傀儡 2024-10-21 20:07:26

如果源和目标重叠,则 strcpy() 的行为正式未定义。

memcpy 的联机帮助页中提出了一个建议:

memcpy()函数将n个字节从内存区域s2复制到内存区域s1。如果 s1 和 s2 重叠,则行为未定义。 s1 和 s2 可能重叠的应用程序应使用 memmove(3)。

The behavior of strcpy() is officially undefined if source and destination overlap.

From the manpage for memcpy comes a suggestion:

The memcpy() function copies n bytes from memory area s2 to memory area s1. If s1 and s2 overlap, behavior is undefined. Applications in which s1 and s2 might overlap should use memmove(3) instead.

韵柒 2024-10-21 20:07:26

答案是肯定的:对于某些编译器/库实现(我猜是最新的),您最终会得到一个虚假的结果。有关示例,请参阅strcpy 是如何实现的?

The answer is yes: with certain compiler/library implementations, newest ones I guess, you'll end up with a bogus result. See How is strcpy implemented? for an example.

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