[英]C - valgrind - invalid read of size 1
我在使用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終止其輸出字符串; 確實,只有在word
比strncpy()
的大小參數短 (以字符數為單位)時,它才會這樣做。
因此,在運行時,使用當前源字符串和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才對此類功能進行標准化。
strncpy (head->word, word, strlen(word));
順便說一句:這不是我第一次看到這種模式。 它如何設法自我傳播? 這個模因的承擔者應該已經全部被自然選擇殺死了(如果僅...)
發明了strncpy
以防止緩沖區溢出 。 緩沖區是函數的第一個參數(在其中填充數據)。 當您嘗試填充更多數據而無法容納時,就會發生溢出。 為了避免這種情況,您可以通過告訴strncpy
緩沖區可以保留多少數據來限制可以填充的數據量。 您通過了緩沖區的大小 。 您無需傳遞必須復制的數據量。 strncpy
完全能夠自己弄清楚。 它不知道可以安全復制多少數據。 這就是為什么您需要在單獨的論點中為此付出多少 。
當然,您必須對字符串進行空終止。 如果使strncpy
充滿了緩沖區的內容, strncpy
將不會為您執行此操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.