C 瓦尔格兰德;“未初始化值”;错误

C 瓦尔格兰德;“未初始化值”;错误,c,linux,memory-management,initialization,valgrind,C,Linux,Memory Management,Initialization,Valgrind,在我的C程序中,我使用malloc()分配内存,这与calloc()不同,它没有初始化内存,并且可能仍然包含垃圾。通常,在分配上下文中,我不会对malloc()分配的内存进行任何更改。(例如,在初始化包含缓冲区的结构的函数中,我不会更改缓冲区的内存,但会在以后更改) Valgrind给了我很多错误: 条件跳转或移动取决于未初始化的值 使用大小为4的未初始化值 在这种情况下,我肯定不会从未初始化的内存中读取数据 我应该忽略它们还是在分配时初始化内存更好?如果我应该忽略它们,我如何在Valgri

在我的C程序中,我使用
malloc()
分配内存,这与
calloc()
不同,它没有初始化内存,并且可能仍然包含垃圾。通常,在分配上下文中,我不会对
malloc()
分配的内存进行任何更改。(例如,在初始化包含缓冲区的结构的函数中,我不会更改缓冲区的内存,但会在以后更改)

Valgrind给了我很多错误:

  • 条件跳转或移动取决于未初始化的值
  • 使用大小为4的未初始化值
在这种情况下,我肯定不会从未初始化的内存中读取数据

我应该忽略它们还是在分配时初始化内存更好?如果我应该忽略它们,我如何在Valgrind中停用此错误消息


示例1

==4253== Conditional jump or move depends on uninitialised value(s)
==4253==    at 0x408EB8E: vfprintf (vfprintf.c:1624)
==4253==    by 0x4093C2E: printf (printf.c:35)
==4253==    by 0x40624D2: (below main) (libc-start.c:226)
==4253==  Uninitialised value was created by a heap allocation
==4253==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253==    by 0x8048938: gk_StreamBufferNode_init (stream.c:101)
==4253==    by 0x8048D0D: gk_Stream_bufferWriteProc (stream.c:252)
==4253==    by 0x8048665: main (main.c:21)
==4253== Conditional jump or move depends on uninitialised value(s)
==4253==    at 0x402DA39: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253==    by 0x8048C6E: gk_Stream_bufferWriteProc (stream.c:230)
==4253==    by 0x8048665: main (main.c:21)
==4253==  Uninitialised value was created by a heap allocation
==4253==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253==    by 0x8048CE0: gk_Stream_bufferWriteProc (stream.c:248)
==4253==    by 0x8048665: main (main.c:21)
代码:


示例2

==4253== Conditional jump or move depends on uninitialised value(s)
==4253==    at 0x408EB8E: vfprintf (vfprintf.c:1624)
==4253==    by 0x4093C2E: printf (printf.c:35)
==4253==    by 0x40624D2: (below main) (libc-start.c:226)
==4253==  Uninitialised value was created by a heap allocation
==4253==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253==    by 0x8048938: gk_StreamBufferNode_init (stream.c:101)
==4253==    by 0x8048D0D: gk_Stream_bufferWriteProc (stream.c:252)
==4253==    by 0x8048665: main (main.c:21)
==4253== Conditional jump or move depends on uninitialised value(s)
==4253==    at 0x402DA39: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253==    by 0x8048C6E: gk_Stream_bufferWriteProc (stream.c:230)
==4253==    by 0x8048665: main (main.c:21)
==4253==  Uninitialised value was created by a heap allocation
==4253==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253==    by 0x8048CE0: gk_Stream_bufferWriteProc (stream.c:248)
==4253==    by 0x8048665: main (main.c:21)
代码:

/**/
int available_bytes=binfo->buffer_size-bnode->filled;
int bytes_to_go=大小*计数;
整数偏移=0;
int node_offset=0;
gk_StreamBufferNode*新_节点;
void*destination=NULL;
void*source=NULL;
while(字节到字节>0){
目的地=节点->缓冲区+节点->填充+节点偏移量;
源=缓冲区+偏移量;
如果(可用字节>字节到字节){
memcpy(目标、源、字节);//第230行
bnode->filled+=bytes\u to\u go;
偏移量+=字节数;
节点偏移量=字节数;
字节\u到\u go=0;
}
否则{
memcpy(目标、源、可用字节);
偏移量+=可用字节;
节点_偏移=0;
字节到字节-=可用字节;
bnode->filled+=可用字节;
#ifdef调试
断言(bnode->filled==bnode->buffer_size);
#endif//DEBUG
//分配一个新的缓冲区节点。
new_node=(gk_StreamBufferNode*)malloc(sizeof(gk_StreamBufferNode));//第248行
if(新节点==NULL){
返回GKIT_FAILEDALLOC;
}
int success=gk\u StreamBufferNode\u init(新的\u节点,binfo->buffer\u大小,
马洛克);
if(success next=new_节点;
bnode=新的_节点;
可用字节数=binfo->buffer\u size;
}
}

您的代码不应该期望未初始化的内存包含任何值,因此依赖于这些值的条件跳转显示出严重的问题


您应该初始化内存(到某个已知值,例如
0
),或者除非已初始化,否则不引用其内容。

在这两种情况下,您只需分配内存,而不进行初始化。最简单的方法是使用
calloc
而不是
malloc
将其归零。对于简单情况,这可能是一个很好的策略,例如,如果以后将
缓冲区
用作要打印的字符串ed.对于更复杂的用例,将值分配给各个字段,或者如果您让C99从复合文字分配整个结构,则更好:

toto * t = malloc(sizeof(*t));    
*t = (toto){ 0 };

你不应该忽略这样的错误。如果你发布一些代码,我们可以帮助你发现一个问题。那里的某个地方也有一个
If
语句,因为它说的是“条件跳转”。@Als我添加了两个示例:即使我确定我从来没有从未初始化的内存中读取过数据,通常当程序从未初始化的内存中读取数据时,作者肯定他们没有从中读取数据。只需说一句。@NiklasR:你是从未初始化的内存中读取的。第一种情况可能是由优化的strlen引起的误报,可能一次读取4个字节,可能读取(但忽略)未初始化的字节。如果您确定它们确实是误报,则可以抑制它们(请参阅valgrind的
--suppressions
--gen suppressions
选项)1。作业应该如何进行?编译器现在不知道
t
所指向的内存块的大小。2.这不是一个太大的开销吗?我绝对肯定不会从未设置的内存中读取。@NiklasR,它知道
*t
的类型,因此这是对
toto
类型的对象赋值。唯一不适用的类型是数组类型、
struct
、整数或浮点类型都可以。对于您声明的读取,我绝对肯定您确实在某处读取了单元化内存,而不是显式地然后隐式地在
printf
中读取。valgrind的发现通常是可靠的。不,与从RAM读取if相比,这不是很大的开销,例如RAM比CPU慢几个数量级。在任何情况下,首先要做对,然后再优化。