Ich kann nicht herausfinden, warum Valgrind Invalid read of size 8
bei Verwendung von wchar_t
druckt. Ich benutze ein 64bit Ubuntu (3.5.0-25) System mit valgrind-3.7.0 und gcc 4.7.2.wchar_t valgrind issue - Ungültiger Lesewert von Größe 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;
}
Compile:
$ gcc -g -std=c99 test.c -o test
$ valgrind --tool=memcheck --leak-check=full --track-origins=yes --show-reachable=yes ./test
Valgrind Ergebnisse:
==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)
Nun, wenn ich das gleiche, aber mit einem 'Arbeits string' laufen, sagen wir mal,
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 bekomme kein Problem:
==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)
Zuerst dachte ich, die Stringgröße sollte immer Vielfaches von 8 sein werden (vielleicht einige wcs lesen Stücke von 8), aber einige Fälle, schlug fehl, dann dachte ich, ich würde immer 8 Byte für den Nullabschluss anhängen haben ((wcslen(item) + 2) * sizeof(wchar_t))
, es hat funktioniert, aber das macht keinen Sinn, seit sizeof(wchar_t)
- in meinem System - ist 4 Bytes und sollte ausreichen, um den L'\0'
Terminator zu behandeln.
Ich lese auch den glibc wcslen
Quellcode, aber nichts neues. Ich denke jetzt an Valgrind Problem. Könnt ihr hier etwas Licht werfen? Lohnt es sich einen Fehler gegen Valgrind zu stellen?
Danke
Vielleicht ein Problem mit Valgrind, ja. Ich bekomme keine Fehler mit der Version 3.8.1 mit Ihrem Code und der gleichen GCC-Version. – teppic
Ändere dies 'new_text = (wchar_t *) malloc ((wcslen (Text) + 1) * sizeof (wchar_t));' wird 'new_text = Calloc (wcslen (Text) + 1, sizeof (* new_text));' und erneut testen. – alk
Als eine Randnotiz - Ihr Code wird nicht funktionieren, wenn Sie _any_ Nicht-ASCII-Zeichen in Ihren Zeichenfolgen verwenden. Sie sollten das Gebietsschema festlegen. – teppic