При запуске memcheck
инструмент VALGRIND, я часто получаю много сотен тысяч (или больше, так как Valgrind отсекает на 100К) малого недействителен чтения заявления, например:Нужно ли беспокоиться о ошибках сообщения Valgrind за пределами моего приложения?
==32027== Invalid read of size 1
==32027== at 0x3AB426E26A: _IO_default_xsputn (in /lib64/libc-2.5.so)
==32027== by 0x3AB426CF70: [email protected]@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
Эти заявления относятся к призывам функций за пределами моя заявка («starch
») и которые, как представляется, являются частью libc
. Это что-то, о чем я должен беспокоиться?
EDIT
Если я изменить fwrite
вызов, чтобы удалить один байт, то мой GZIP поток будет поврежден. Вот исходный код:
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
Я думаю, что я вижу проблему. У меня есть in[STARCH_Z_CHUNK]
, а не in[STARCH_Z_CHUNK + 1]
(а также для out[]
). Если я регулирую оба оператора fread
и fwrite
по -1
, не похоже, чтобы получить эти Invalid read of size 1
заявления, хотя я до сих пор вижу много Invalid read of size 4
и 8
, которые являются специфическими для zlib
:
==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
Я перекомпиляю с -g
, который, как уже упоминалось, связывает номера строк с ошибками.
Но я просто делаю несложные strncpy
из argv[]
переменных, например .:
strncpy(uniqTag, argv[2], strlen(argv[2]) + 1);
Это необходимо скопировать над нулем в конце argv[2]
строки в uniqTag
, но valgrind
до сих пор отмечает это как ошибку.
EDIT 4
Вот сообщение об ошибке:
==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
Вот две соответствующие строки; Valgrind говорит вторая строка является недопустимым для чтения:
uniqTag = (char *)malloc(strlen(argv[2]) + 1);
strncpy(uniqTag, argv[2], strlen(argv[2]) + 1);
Поскольку strlen(argv[2]) + 1 > strlen(argv[2])
, это должно привести к нулевому байту uniqTag
.
На самом деле это, вероятно, ваш буфер, который должен быть немного больше, а не fwrite(), который должен сдерживать себя ... – thkala
Попробуйте увеличить размер буферов на 1 и посмотреть, что произойдет – thkala
BTW, вы компиляция кода с помощью отладочных символов? Если вы используете -g в параметрах компилятора (при условии, что вы используете gcc), valgrind выдаст более точные и полезные сообщения. – thkala