2013-03-22 4 views
8

wchar_t을 사용할 때 Valgrind가 Invalid read of size 8을 인쇄하는 이유를 알 수 없습니다. 저는 valgrind-3.7.0 및 gcc 4.7.2를 사용하는 64 비트 우분투 (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 

I 문제가되지 않는다 :

012 처음에는 3,516,
==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) 

나는 문자열 크기는 항상 (어쩌면 일부 WCS 8의 덩어리를 읽기) 8의 배수가되어야한다고 생각하지만, 어떤 경우는, 그때 내가 NULL 종결 항상 8 바이트를 추가 할 거라고 생각 실패 ((wcslen(item) + 2) * sizeof(wchar_t)), 그것은 작동하지만, 내 시스템에서 sizeof(wchar_t) - 4 바이트이므로 L'\0' 터미네이터를 처리하기에 충분해야하므로 의미가 없습니다.

나는 glibc wcslen 소스 코드를 읽었지만 새로운 것은 없다. 나는 이제 Valgrind 문제를 생각하고있다. 너희들 여기 빛을 던질 수 있니? Valgrind와 관련하여 버그를 신고 할 가치가 있습니까?

당신에게

+0

아마도 valgrind의 문제 일 수 있습니다. 귀하의 코드와 동일한 gcc 버전으로 버전 3.8.1에서 오류가 발생하지 않습니다. – teppic

+0

new_text = calloc (wcslen (text) + 1, sizeof (* new_text));이'new_text = (wchar_t *) malloc ((wcslen (text) +1) * sizeof (wchar_t) 재시험. – alk

+0

부수적으로 - 문자열에 _any_ ASCII가 아닌 문자를 사용하면 코드가 작동하지 않습니다. 로케일을 설정해야합니다. – teppic

답변

6

이 아마 wcslen 기능의 SSE 최적화에 의해 발생합니다 감사; 예를 들어 https://bugzilla.redhat.com/show_bug.cgi?id=798968 또는 https://bugs.archlinux.org/task/30643.

wcslen를 최적화, 그것은 한 번에 여러 다양한 문자를 읽고 L'\0'로 비교 명령 (SSE)를 벡터화 사용하는 것이 더 빠릅니다. 불행히도 valgrind는 이것을 초기화되지 않은 읽기로 간주합니다. 즉, wcslen의 결과는 초기화되지 않은 값에 의존하지 않으므로 무해합니다.

수정 사항은 더 새로운 버전이 오 탐지 (false positive)를 억제 할 것이라는 희망으로 valgrind를 업데이트하는 것입니다.