Muss ich Sorge über Valgrind Fehler außerhalb des Bereichs meiner Bewerbung Berichterstattung?
Frage
Wenn Valgrind des memcheck
Werkzeug läuft, habe ich oft viele Hunderttausende (oder mehr, da Valgrind schneidet bei 100 K off) erhalten von kleinen ungültigen Lese Aussagen, z.
==32027== Invalid read of size 1
==32027== at 0x3AB426E26A: _IO_default_xsputn (in /lib64/libc-2.5.so)
==32027== by 0x3AB426CF70: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==32027== by 0x3AB42621FA: fwrite (in /lib64/libc-2.5.so)
==32027== by 0x4018CA: STARCH_gzip_deflate (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027== by 0x401F48: compressFileWithGzip (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027== by 0x4028B5: transformInput (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027== by 0x402F12: main (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32027== Address 0x7febb9b3c is on thread 1's stack
beziehen sich diese Aussagen auf Aufrufe von Funktionen außerhalb meiner Anwendung ( „starch
“) und die Teil libc
zu sein scheinen. Ist das etwas, das ich mit betroffen sein?
Bearbeiten
Wenn ich den fwrite
Aufruf ändert ein Byte zu entfernen, dann wird mein gzip Strom beschädigt. Hier ist der ursprüngliche Code:
int STARCH_gzip_deflate(FILE *source, FILE *dest, int level) {
int ret, flush;
unsigned have;
z_stream strm;
unsigned char in[STARCH_Z_CHUNK];
unsigned char out[STARCH_Z_CHUNK];
/* initialize deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
/* deflateInit2 allows creation of archive with gzip header, i.e. a gzip file */
/* cf. http://www.zlib.net/manual.html */
ret = deflateInit2(&strm, level, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);
if (ret != Z_OK)
return ret;
/* compress until end of file */
do {
strm.avail_in = fread(in, 1, STARCH_Z_CHUNK, source);
if (ferror(source)) {
(void)deflateEnd(&strm);
return Z_ERRNO;
}
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;
do {
strm.avail_out = STARCH_Z_CHUNK;
strm.next_out = out;
ret = deflate(&strm, flush);
assert(ret != Z_STREAM_ERROR);
have = STARCH_Z_CHUNK - strm.avail_out;
/* invalid read happens here */
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)deflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
assert(strm.avail_in == 0);
} while (flush != Z_FINISH);
assert(ret == Z_STREAM_END);
/* clean up and return */
(void)deflateEnd(&strm);
return Z_OK;
}
EDIT 2
Ich denke, dass ich das Problem zu sehen. Ich habe in[STARCH_Z_CHUNK]
und nicht in[STARCH_Z_CHUNK + 1]
(und ebenso für out[]
). Wenn ich beide der fread
und fwrite
Erklärungen -1
einstellen, scheine ich nicht jene Invalid read of size 1
Aussagen zu bekommen, obwohl ich immer noch eine Menge Invalid read of size 4
und 8
sehen, die spezifisch für zlib
sind:
==32624== Invalid read of size 4
==32624== at 0x3AB5206455: deflateInit2_ (in /usr/lib64/libz.so.1.2.3)
==32624== by 0x40180E: STARCH_gzip_deflate (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624== by 0x401F48: compressFileWithGzip (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624== by 0x402C03: transformInput (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624== by 0x402F12: main (in /home/areynolds/trunk/utility/applications/bed/starch/bin/starch)
==32624== Address 0x7feafde38 is on thread 1's stack
EDIT 3
ich mit -g
bin neu zu kompilieren, die, wie erwähnt, tun Associate Zeilennummern mit Fehlern.
Aber ich bin nur eine einfache strncpy
von argv[]
Variablen zu tun, z.
strncpy(uniqTag, argv[2], strlen(argv[2]) + 1);
Dies sollte die nullterminierte argv[2]
Zeichenfolge uniqTag
kopieren vorbei, aber valgrind
noch markiert diese als Fehler.
EDIT 4
Hier ist die Fehlermeldung:
==3682== Invalid read of size 1
==3682== at 0x4A081C1: strncpy (mc_replace_strmem.c:329)
==3682== by 0x4022F1: parseCommandLineInputs (starch.c:589)
==3682== by 0x402F20: main (starch.c:46)
==3682== Address 0x7fedffe11 is on thread 1's stac
Hier sind die beiden relevanten Linien; valgrind sagt die zweite Zeile ist eine ungültige Lese:
uniqTag = (char *)malloc(strlen(argv[2]) + 1);
strncpy(uniqTag, argv[2], strlen(argv[2]) + 1);
Da strlen(argv[2]) + 1 > strlen(argv[2])
, diese in einem nullterminierten uniqTag
führen sollten.
Lösung
In diesem Fall würde ich sagen, dass Sie das tun. Die libc Funktionsargumente kommen aus Ihrem Programm. Ich würde eine Vermutung Gefahr und sagen, dass Sie durch einen Fehler im Code ein Off haben, dass Leitungen fwrite ein Byte nach dem Ende seiner Quellenpuffer zu lesen.
EDIT:
Durch die Art und Weise, wie ein kleiner Fehler kann oft unsichtbar bleiben (das heißt den Code nicht abstürzt) beide, da der Compiler und die Speicherzuweisung in der Regel Speicherblocks in bestimmten Größen zuzuordnen und sie an Wort Kanten ausrichten. Dies bedeutet, dass viele Male gibt es einen kleinen Bereich hinter dem angeforderten Pufferendplatte, dass Sie ohne Auslösen des Speicherschutz-Code zugreifen können. Natürlich könnten Sie den Code nur brechen, wenn Sie Compiler ändern, libc, Plattform oder Bitness (z.B. 64 bis 32 Bit gehen).
Valgrind hat Unterdrückungslisten für die erwarteten Fehler in libc, die Sie in der Regel bei /usr/lib64/valgrind/default.supp oder /usr/lib/valgrind/default.supp finden. Es gibt durchaus ein paar Probleme, die valgrind erkennt in libc, viele von ihnen in dem Bemühen, vorsätzlichen den Code zu optimieren, aber aufgrund der suppresions in 99% der Fälle ist es der getesteten Code, der das Problem verursacht.
EDIT2:
Beachten Sie, dass, wie die meisten Debugging-Tools, Valgrind ausgeben wird unendlich mehr nützliche Informationen zu den Themen erkennt es, wenn Sie Ihren Code mit Debug-Symbole kompilieren. Es können Sie auf bestimmte Codezeilen zeigen, die mit dem Problem verknüpft sind - auch wenn sie oft nicht, wo das eigentliche Problem liegt ist. Wenn Sie GCC hinzu, um dessen Möglichkeiten nutzen, nur -g, um Ihren Code mit Debug-Symbolen zu kompilieren. In einer Produktions Release, aber denken Sie bitte daran, dass die Flagge zu entfernen!
Andere Tipps
Sie sollten den Call-Stack folgen, bis Sie zu einem gewissen Code, der Ihnen und sucht die Fehler des Ursprungs ist. In diesem Fall erscheint STARCH_gzip_deflate
fwrite
mit etwas zu fordern, was schlecht ist (wahrscheinlich eine schlechte FILE *
oder der Puffer Sie versuchen, zu schreiben), die die valgrind zu bellen Sie verursacht.
Es ist möglich, dass dies nicht wirklich ein Fehler ist oder dass es nicht Ihre Fehler ist, though. Aber es wahrscheinlich ist.