c - Valgrind, "uninitialized value(s)"错误

标签 c linux memory-management initialization valgrind

在我的 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)

代码:

int gk_StreamBufferNode_init(gk_StreamBufferNode* node, int buffer_size,
                             gk_AllocProc malloc) {
    node->buffer = malloc(buffer_size);     // line 101
    if (node->buffer == NULL) {
        return GKIT_FAILEDALLOC;
    }
    node->next = NULL;
    return GKIT_NOERR;
}

示例 2:

==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 = size * count;
    int offset = 0;
    int node_offset = 0;
    gk_StreamBufferNode* new_node;
    void* destination = NULL;
    void* source = NULL;

    while (bytes_to_go > 0) {
        destination = bnode->buffer + bnode->filled + node_offset;
        source = buffer + offset;
        if (available_bytes > bytes_to_go) {
            memcpy(destination, source, bytes_to_go);    // line 230
            bnode->filled += bytes_to_go;
            offset += bytes_to_go;
            node_offset = bytes_to_go;
            bytes_to_go = 0;
        }
        else {
            memcpy(destination, source, available_bytes);
            offset += available_bytes;
            node_offset = 0;
            bytes_to_go -= available_bytes;
            bnode->filled += available_bytes;

            #ifdef DEBUG
                assert(bnode->filled == bnode->buffer_size);
            #endif // DEBUG

            // Allocate a new buffer node.
            new_node = (gk_StreamBufferNode*) malloc(sizeof(gk_StreamBufferNode));    // line 248
            if (new_node == NULL) {
                return GKIT_FAILEDALLOC;
            }
            int success = gk_StreamBufferNode_init(new_node, binfo->buffer_size,
                                                   malloc);
            if (success <= GKIT_ERROR) {
                free(new_node);
                return GKIT_FAILEDALLOC;
            }
            bnode->next = new_node;
            bnode = new_node;
            available_bytes = binfo->buffer_size;
        }
    }

最佳答案

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

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

关于c - Valgrind, "uninitialized value(s)"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11246344/

相关文章:

c++ - 资源容器的包装

c - char *(arr[5]) 和 char (*arr)[5] 之间的区别

c - 队列函数的棘手 C 代码,指针发生了什么?

c - 当 for 循环中有逗号而不是分号时,没有编译器警告

Python子进程输出格式?

linux - rpmbuild 正在/usr/local 中构建我的目标目录,而不是我指定的位置

c - 将使用 MSYS2 和 MingW 构建的程序发送给最终用户的正确方法是什么?

c - g_strdup_printf 中不需要的换行符或空符号

linux - 是否有一个目录可以放置一个 d 文件,以便编译器自动包含它?

c++ - 在定义结构之前如何使用指向结构的指针?