C - valgrind - 大小为 1 的无效读取

标签 c profiling valgrind

我在使用 Valgrind 调试我的代码时遇到了一些问题。这是出现错误的结构和主要部分:

struct trieNode {
    char *word;
    struct trieNode *(subNode[LEAF_NUM]);
    struct sharpNode *sharp;    
};


//linked list of sharp(s)
struct sharpNode {
    char *word;
    struct sharpNode *next;
}; 

if (head->word == NULL){ 
    //strlen(head->word) == 0){
    head->word = (char *)malloc(MAX_LEN * sizeof(char));     //LINE 191
    //memset(head->word, '\0',strlen(head->word));
    strncpy (head->word, word, strlen(word));

} else { 

    if (head->sharp == NULL) {
        head->sharp = sharpNodeCreate();
        head->sharp->word = (char *)malloc(MAX_LEN * sizeof(char));    //LINE 200
        //head->sharp->word[strlen(word)] = '\0';
        strncpy (head->sharp->word, word, strlen(word));
    }

}

            } else if ( sharpIndex == 0 && strlen(trie_ptr->word) > 0) {
                printf("%s\n", trie_ptr->word);         //LINE 135
            } else if (notSharp == 0 && sharp_ptr != NULL) {
                printf("%s\n", sharp_ptr->word);       //LINE 137
            }  else {
                printf("There are no more T9onyms\n");
            }

当我运行 valgrind 时,它会提示:

==20040== Invalid read of size 1
==20040==    at 0x4A09264: __GI_strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20040==    by 0x334BC6DD2B: puts (in /usr/lib64/libc-2.17.so)
==20040==    by 0x400C2C: lookupTrie (trie.c:135)
==20040==    by 0x400905: main (t9.c:23)
==20040==  Address 0x4c4e2f4 is 0 bytes after a block of size 4 alloc'd
==20040==    at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20040==    by 0x400D6B: populateTrie (trie.c:191)
==20040==    by 0x4008F9: main (t9.c:22)
==20040== 
ace

Enter Key Sequence (or "#" for next word):
#
==20040== Invalid read of size 1
==20040==    at 0x4A09264: __GI_strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20040==    by 0x334BC6DD2B: puts (in /usr/lib64/libc-2.17.so)
==20040==    by 0x400C4A: lookupTrie (trie.c:137)
==20040==    by 0x400905: main (t9.c:23)
==20040==  Address 0x4dad294 is 0 bytes after a block of size 4 alloc'd
==20040==    at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==20040==    by 0x400DDA: populateTrie (trie.c:200)
==20040==    by 0x4008F9: main (t9.c:22)

有人能指出我正确的方向吗?

最佳答案

你得到的错误是由于

strncpy (head->word, word, strlen(word));

strncpy (head->sharp->word, word, strlen(word));

不以 NUL 字符终止他们的目标。 strncpy() 并不总是以 NUL 结尾它的输出字符串;实际上,只有当 wordstrncpy() 的大小参数更短(以字符数计)时,它才会这样做。

因此,在运行时,您当前的源字符串和大小参数为 strncpy()(其中单词中的字符数正好等于且不短 比大小参数),strncpy() 不会在 head->word 的末尾写入 NUL 字符。但是当 printf 尝试打印您的字符串时,它必须隐式地找到该字符串的结尾,以其终止 NUL 字符标记。因此,它会读取您分配的所有缓冲区,但未能找到 NUL 字符,并且完全靠运气在缓冲区末尾后找到一个,因此不会崩溃。尽管如此,这是一个无效的阅读; Valgrind 为您找到了它,但您必须修复它。

要修复它,我建议您将 strncpy() 的大小参数替换为 MAX_LEN-1,并使用 手动终止字符串复制>head->word[MAX_LEN-1] = '\0'.

或者你可以像我之前做的那样,自己实现一个 strzcpy(char* d, char* s, size_t len) 函数来复制 len-1 个字符和 NUL 终止。遗憾的是,这样的功能直到 C11 才被标准化。

关于C - valgrind - 大小为 1 的无效读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22123779/

相关文章:

c - Peterson的线程链表算法(C语言)

c - 使用数组和随机数循环打印一个简单的 5 x 5 板

C 编程 - 将字符分配给盲文点

python - 有效地计算没有尾随零的阶乘?

performance - 这个执行时间的正确术语是什么?

c - Valgrind 内存泄漏可达

c - 当无法更改数组的地址时,strcpy() 如何将字符串复制到数组?

c++ - 与 Valgrind 一起运行时,malloc 返回 null

c - malloc.c :3074 + Valgrind output

c++ - Visual Studio 2013 分析 Cinder 项目时,没有出现单个函数调用