Valgrind 警告:我应该认真对待它吗
背景: 我有一个模仿 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
标准可能没有指定这些缓冲区重叠时会发生什么。所以,是的,valgrind 对此的抱怨是正确的。
实际上,您很可能会发现您的
strcpy
按从左到右的顺序复制(例如while (*dst++ = *src++);< /code>) 并且这不是问题。但它仍然不正确,并且在与其他 C 库一起运行时可能会出现问题。
一种标准正确的编写方法是:
因为
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:
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, sincestrlen(newBuff)
should equalstrlen(newBuff+1)+1
, which is what I originally wrote.)是的,您还应该担心您的函数具有病态的糟糕性能(对于本应为
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 beO(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.是的 - 仅当源和目标不重叠时才定义
strcpy
的行为。您可以考虑将strlen
和memmove
组合起来。Yes -- the behavior of
strcpy
is only defined if the source and dest don't overlap. You might consider a combination ofstrlen
andmemmove
instead.是的,你应该担心。 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.如果源和目标重叠,则 strcpy() 的行为正式未定义。
memcpy 的联机帮助页中提出了一个建议:
The behavior of
strcpy()
is officially undefined if source and destination overlap.From the manpage for memcpy comes a suggestion:
答案是肯定的:对于某些编译器/库实现(我猜是最新的),您最终会得到一个虚假的结果。有关示例,请参阅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.