2014-03-02 124 views
1

我在使用Valgrind调试代码时遇到了一些麻烦。这里就是错误出现的结构和主要部件:C - valgrind - 大小为1的无效读取

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) 

能有人指出我在右边irection?

+0

'head-> sharp = sharpNodeCreate();','sharpNodeCreate()'做了什么? – brokenfoot

+1

在'strncpy(head-> word,word,strlen(word));','word'(第二个参数)是什么? – brokenfoot

回答

4

你得到的错误是由于

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

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

不是NULL字符终止他们的目标。 strncpy()并不总是NUL终止其输出字符串;实际上,只有在word时,(在字符数中)大于strncpy()的大小参数时才会这样做。

因此,在运行时,并与电流源串和尺寸参数strncpy()(其中在单词中的字符数是精确等于和不短比尺寸参数),NUL字符在head->word的末尾不是由strncpy()写的。但是,当printf尝试打印您的字符串时,它必须隐式地找到该字符串的结尾,并以其终止的NUL字符标记。因此,它会读取所有分配的缓冲区找不到NUL字符,纯粹通过运气在缓冲区结束后找到一个缓冲区,从而不会崩溃。不过,这是一个无效的阅读; Valgrind为你找到了它,但你必须修复它。

要解决这个问题,我建议你用MAX_LEN-1替换strncpy()的大小参数,并且手动终止字符串副本head->word[MAX_LEN-1] = '\0'

或者你可以像我之前做的那样做,并实现自己的strzcpy(char* d, char* s, size_t len)函数,该函数复制len-1字符和NUL终止。在C11之前,这样的功能并不是标准化的,这是一种耻辱。

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

另外:这不是我第一次看到这种模式。它如何设法传播自己?这个说法的火炬手应该已经全部通过自然选择已经杀(如果只有...)

strncpy的发明是为了防止缓冲区溢出。缓冲区是函数的第一个参数(在这里填充数据)。当您尝试填充更多数据时,会发生溢出,而不是容纳数据。为了防止这种情况发生,您可以通过告诉strncpy限制数据量。多少数据缓冲区可以保留。你通过BUFFER的大小。你不会传递你需要复制的数据量。 strncpy是完全能够弄清楚它自己。它不知道要复制多少数据安全这就是为什么你需要在单独的论据中通过它。

这是否足够清楚,还是应该放大字体并使其闪烁红色?

当然,你必须null-终止你的字符串。 strncpy不会为你做,如果你让它填补你的缓冲区边缘。