Я приведу несколько примеров.
#include <stdlib.h>
int main(void)
{
int*pi1 = malloc(10*sizeof(int));
if (pi1[5]) // ERROR here, see 4.2.2 in the manual
;
free(pi1);
int* pi2 = malloc(10*sizeof(int));
free(pi2);
if (pi2[5]) // ERROR here, a variation of 4.2.1 in the manual
;
int* pi3 = (int*)0x500000000000U;
if (*pi3) // ERROR and probably a crash, see 4.2.1 in the manual
;
}
Очевидно, что это тривиальные примеры. В более сложных проблемах реального мира вы должны знать, что «неинициализированная» природа памяти является транзитивной. Valgrind не выдает сообщений об ошибках, пока использование неинициализированной памяти не повлияет на поведение программного обеспечения.
Например, вы можете иметь
- Структура s1, выделенная с помощью mallo c.
- Все поля s1 инициализируются, кроме f1.
- s1 копируется в s2. Ошибка не выдается.
- s2 копируется в s3. Ошибка не выдается.
- На s3.f1 выполняется чтение. Теперь Valgrind выдает ошибку. Это даст стек здесь и стек выделения на шаге 1.