Valgrind пытается определить, зависит ли значение от инициализированной памяти или нет, что в общем-то не является проблемой, которую можно устранить. Valgrind делает все возможное, отслеживая, какие биты установлены, и позволяя им каскадироваться. Есть много способов обмануть это. Например, я только что приготовил этот код:
#include <stdlib.h>
int main(int argc, char *argv[])
{
unsigned *p = malloc(sizeof(unsigned));
unsigned x = *p;
free(p);
unsigned f = x == 0;
unsigned g = x == 1;
return f & g;
}
Примечание: Вышеуказанная программа, строго говоря, правильная на любой платформе, которая не имеет представления прерываний для unsigned int
, что верно для нашей платформы (Valgrind только для x86) Неопределенное поведение не вызывается на этих платформах, и main
гарантируется стандартом C для возврата 0 на таких платформах.
Образец цитирования: n1256: 7.20.3.3: malloc
возвращает объекты, значения которых являются "неопределенными". n1256 3.17.2: неопределенное значение является либо «представлением ловушки», либо «неопределенным значением». Обратите внимание, что в x86 нет целых представлений для целых чисел без знака.
Согласно Valgrind, ни f
, ни g
не инициализированы должным образом, поэтому f & g
также нельзя инициализировать. Тем не менее, результат всегда равен нулю, как вам скажет любой, имеющий унцию логики. Valgrind не понимает логику, он просто следует битам по некоторым простым правилам.
Вероятно, здесь происходит то, что компилятор Intel C дал вам оптимизированную версию strlen
, которая использует SSE или какую-то хитрость, которая привела к тому, что «неинициализированные» биты в Valgrind были установлены в результате. Естественно, это произошло бы, если бы оптимизированный код прочитал после , инициализировал часть buf
, а затем выполнил серию операций, подобных описанным выше. И, конечно, он будет делать что-то подобное, потому что так делать быстрее (и всегда безопасно читать после конца массивов в x86, если вы не пересекаете границу страницы). У вас есть несколько вариантов.
Отключить оптимизацию при использовании Valgrind и компилятора Intel.
Добавьте код в Valgrind, чтобы поймать этот тип ошибки. (В Valgrind уже есть особые случаи.)
Измените ваш код условно, чтобы Valgrind дал правильный результат. Например, поместите это вверху:
// This only fixes the error if sizeof(buf) is at least as large
// as the largest multiple of 16 larger than strlen(buf)
#if VALGRIND
memset(buf, '\0', sizeof(buf));
#endif