2013-03-22 58 views
8

的無效讀我無法弄清楚爲什麼Valgrind的使用wchar_t時打印Invalid read of size 8。我正在運行一個帶有valgrind-3.7.0和gcc 4.7.2的64位Ubuntu(3.5.0-25)系統。wchar_t的Valgrind的問題 - 大小8

#include <stdio.h> 
#include <wchar.h> 
#include <stdlib.h> 
#include <string.h> 

int main() 
{ 
    // const wchar_t *text = L"This is a t"; // no Valgrind error 
    // const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error 
    const wchar_t *text = L"This is a test"; // Valgrind ERRROR 

    wchar_t *new_text = NULL; 

    new_text = (wchar_t*) malloc((wcslen(text) + 1) * sizeof(wchar_t)); 
    wcsncpy(new_text, text, wcslen(text)); 
    new_text[wcslen(text)] = L'\0'; 

    printf("new_text: %ls\n", new_text); 

    free(new_text); 

    return 0; 
} 

編譯:

$ gcc -g -std=c99 test.c -o test 
$ valgrind --tool=memcheck --leak-check=full --track-origins=yes --show-reachable=yes ./test 

Valgrind的結果:

==19495== Memcheck, a memory error detector 
==19495== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==19495== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==19495== Command: ./test 
==19495== 
==19495== Invalid read of size 8 
==19495== at 0x4ED45A7: wcslen (wcslen.S:55) 
==19495== by 0x4ED5C0E: wcsrtombs (wcsrtombs.c:74) 
==19495== by 0x4E7D160: vfprintf (vfprintf.c:1630) 
==19495== by 0x4E858D8: printf (printf.c:35) 
==19495== by 0x4006CC: main (test.c:16) 
==19495== Address 0x51f1078 is 56 bytes inside a block of size 60 alloc'd 
==19495== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==19495== by 0x40066F: main (test.c:12) 
==19495== 
new_text: This is a test 
==19495== 
==19495== HEAP SUMMARY: 
==19495==  in use at exit: 0 bytes in 0 blocks 
==19495== total heap usage: 1 allocs, 1 frees, 60 bytes allocated 
==19495== 
==19495== All heap blocks were freed -- no leaks are possible 
==19495== 
==19495== For counts of detected and suppressed errors, rerun with: -v 
==19495== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2) 

現在,如果我跑相同,但有一個 '工作串',讓我們說

const wchar_t *text = L"This is a t"; // no Valgrind error 
// const wchar_t *text = L"This is a teeeeeeee"; // no Valgrind error 
// const wchar_t *text = L"This is a test"; // Valgrind ERRROR 

我沒有問題:

==19571== Memcheck, a memory error detector 
==19571== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==19571== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==19571== Command: ./test 
==19571== 
new_text: This is a t 
==19571== 
==19571== HEAP SUMMARY: 
==19571==  in use at exit: 0 bytes in 0 blocks 
==19571== total heap usage: 1 allocs, 1 frees, 48 bytes allocated 
==19571== 
==19571== All heap blocks were freed -- no leaks are possible 
==19571== 
==19571== For counts of detected and suppressed errors, rerun with: -v 
==19571== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) 

起初我還以爲字符串大小應該始終是多個的8(也許有些WCS讀的8塊),但某些情況下失敗了,那麼我想我不得不追加總是8個字節爲NULL結束((wcslen(item) + 2) * sizeof(wchar_t)),它的工作,但不會使任何意義,因爲sizeof(wchar_t) - 在我的系統 - 爲4個字節,應足以應付L'\0'終止。

我也看了glibc的wcslen源代碼,但不是什麼新鮮事。我現在正在考慮Valgrind問題。你們可以在這裏扔一些光嗎?是否值得向Valgrind提交錯誤?

謝謝

+0

也許隨着Valgrind的一個問題,是的。使用您的代碼和相同的gcc版本,我無法獲得版本3.8.1的錯誤。 – teppic 2013-03-22 14:48:14

+0

更改此'NEW_TEXT =(wchar_t的*)malloc的((wcslen(文本)+ 1)*的sizeof(wchar_t的));'成爲'NEW_TEXT =釋放calloc(wcslen(文本)+ 1,的sizeof(* NEW_TEXT));'並重新測試。 – alk 2013-03-22 14:59:13

+0

請注意 - 如果您在字符串中使用_any_非ASCII字符,您的代碼將無法使用。你應該設置語言環境。 – teppic 2013-03-22 15:17:23

回答

6

這可能是由wcslen功能的SSE優化所致;見例如https://bugzilla.redhat.com/show_bug.cgi?id=798968https://bugs.archlinux.org/task/30643

當優化wcslen,它的速度更快同時讀取多個寬字符,並使用向量化指令(SSE)來比較他們L'\0'。不幸的是valgrind認爲這是一個未初始化的讀 - 它是,但它是無害的,因爲wcslen的結果不依賴於未初始化的值。

解決辦法是,希望一個新的版本將抑制假陽性更新的valgrind。