valgrind 对未初始化值的抱怨会是误报吗?
所以我一直在自学 C,并希望从一开始就学习如何正确管理内存并编写更好的代码,我一直在所有内容上运行 Valgrind。这帮助我解决了内存泄漏问题,但我似乎无法摆脱这种“条件跳转或移动取决于未初始化值/未初始化值是由堆分配创建”的情况,尽管我已经缩小了范围到这段代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* test = (char*) malloc(3);
strncpy(test, "123", 2);
printf("%s\n", test);
free(test);
return 0;
}
当我使用 ---track-origins=yes
运行 Valgrind 时,我得到以下输出:
==91702== Conditional jump or move depends on uninitialised value(s)
==91702== at 0x100011507: strlen (mc_replace_strmem.c:282)
==91702== by 0x1000AA338: puts (in /usr/lib/libSystem.B.dylib)
==91702== by 0x100000EFA: main (valgrind_test.c:10)
==91702== Uninitialised value was created by a heap allocation
==91702== at 0x100010345: malloc (vg_replace_malloc.c:236)
==91702== by 0x100000EEA: main (valgrind_test.c:8)
这对我来说似乎是误报,但我对自己的能力不够有信心自己的知识就这样把它写掉。也许我分配错误或使用 strncpy 错误?我不知道。
提前致谢
So I've been teaching myself C, and in the hopes of learning how to properly manage memory from the beginning and write better code, I've been running Valgrind on everything. This has helped me with memory leaks, but I can't seem to get rid of this "Conditional jump or move depends on uninitialised value(s)/Uninitialised value was created by a heap allocation" situation, although I've narrowed it down to this block of code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* test = (char*) malloc(3);
strncpy(test, "123", 2);
printf("%s\n", test);
free(test);
return 0;
}
When I run Valgrind with ---track-origins=yes
, I get this output:
==91702== Conditional jump or move depends on uninitialised value(s)
==91702== at 0x100011507: strlen (mc_replace_strmem.c:282)
==91702== by 0x1000AA338: puts (in /usr/lib/libSystem.B.dylib)
==91702== by 0x100000EFA: main (valgrind_test.c:10)
==91702== Uninitialised value was created by a heap allocation
==91702== at 0x100010345: malloc (vg_replace_malloc.c:236)
==91702== by 0x100000EEA: main (valgrind_test.c:8)
This seems like a false positive to me, but I'm not confident enough in my own knowledge to write it off as such. Maybe I'm allocating wrong or using strncpy wrong? I'm not sure.
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不,这是损坏的代码。
您有一个包含 3 个未初始化字符的内存块。然后将
"12"
复制到其中,并且不要终止。当心strncpy()
。我引用文档:
由于源的前 2 个字符内没有终止符,因此目标不会终止。
No, this is broken code.
You have a memory block with 3 uninitialized characters. Then you copy
"12"
into it, and don't terminate. Beware ofstrncpy()
.I quote the documentation:
Since there is no termination within the first 2 characters of the source, the destination is not terminated.
使用
strcpy()
和strncpy()
的惯用方法:如果您知道缓冲区有空间容纳字符串加上 NUL 终止符,则可以使用
strcpy( )
。这可能会使用常量,或者在代码中进行检查(您应该确保检查是正确的)。否则,您可以这样做:
这样做有以下缺点:
length
字节。还有 OpenBSD 的
strlcpy()
。strcpy()/strncpy()
的任何其他使用都可能可疑,您应该仔细查看它们。底线:避免使用 C 字符串函数来处理任何中等复杂的内容,尝试使用一些库来动态分配字符串。 Qmail/Postfix 自己推出,GNU 有 obstacks。
Idiomatic ways to use
strcpy()
andstrncpy()
:If you know that the buffer has space for the string plus the NUL terminator, you can use
strcpy()
. This will probably use constants, or have checks in code (you should make sure the checks are right).Otherwise, you can do:
which has the following disadvantages:
length
bytes.There is also OpenBSD's
strlcpy()
.Any other use of
strcpy()/strncpy()
is potentially suspicious, and you should look at them carefully.Bottom line: avoid C string functions for anything moderately complex, try to use some library for dynamically allocated strings. Qmail/Postfix roll their own, GNU has obstacks.
你的字符串没有终止符,所以 valgrind 在它抱怨时可能是正确的。更改:
至:
Your string has no terminator, so valgrind is probably right when it complains. Change:
to: