Valgrind Сравнение указателя с NULL

Я использую Valgrind для отладки своего кода и получаю предупреждение, когда проверяю, struct инициализируется путем сравнения его с NULL,

void main()
{
    int *unassignedPointer;
    if(unassignedPointer == NULL)
        printf("This Pointer is NULL\n");
}

Этот код компилируется и запускается, но при запуске через Valgrind выдает предупреждение: условный переход или перемещение зависит от неинициализированных значений. Весь смысл сравнения с NULL определить, инициализирован ли он или нет. Это опасная практика, или я должен просто игнорировать эти предупреждения?

4 ответа

Решение

Конечно, вы не должны игнорировать предупреждение, вы должны исправить его, инициализируя указатель:

int *pointer = NULL;

как правило, вы не можете определить, была ли назначена переменная, нет волшебного значения "нет значения", все биты переменной используются для хранения действительного значения.

unassignedPointer является унитарной локальной переменной, и чтение такой переменной приведет к неопределенному поведению, то есть вы никогда не будете знать, что произойдет. На большинстве архитектур эти переменные будут просто содержать мусор в памяти, и ваш код ничего не напечатает или "Этот указатель равен NULL" в зависимости от вашей удачи. Вы должны правильно инициализировать переменную:

void main()
{
  int *unassignedPointer = NULL;
  if(unassignedPointer == NULL)
  printf("This Pointer is NULL\n");
}

Во первых здесь

int *unassignedPointer; /*here it can points to any unknown memory location */ 

unassignedPointer не инициализируется и не указывает на правильное расположение в памяти и разыменование (если вы пытались), это вызывает неопределенное поведение. ваш компилятор может предупредить вас как

unassignedPointer используется неинициализированным в этой функции [-Werror=uninitialized]

если вы скомпилировали свой код с соответствующим флагом предупреждения, как -Wall и т.д., поэтому сначала инициализируйте unassignedPointer с NULL лайк

int *unassignedPointer = NULL;

Это опасная практика, или я должен просто игнорировать эти предупреждения? никогда не следует игнорировать предупреждение компилятора. Лучше скомпилировать любой простой код с

gcc -Wall -Wstrict-prototypes -Werror test.c   /* Werror, stops the compilation, convert warning into error */ 

Также прочитайте C языковой стандарт, черновик n1256, раздел 5.1.2.2.1

Запуск программы: должен быть определен с типом возврата int и без параметров:

int main(void) { /*
...
*/ }

или с двумя параметрами (именуемыми здесь как argc и argv, хотя можно использовать yn ames, поскольку вы локальны для функции, в которой вы объявили):

int main(int argc, char *argv[]) { /*
...
*/ }

это

void main() { 
   /*some code */
}

не правильно, вместо этого используйте

int main(void) {
    /*some code */
}

Когда переменная неинициализирована, это означает, что ей не было задано начальное значение. Это означает, что он может иметь любое значение, включая NULL или какое-либо другое значение.

Формально, неинициализированная переменная, которая не имеет статической длительности хранения (т.е. локальная переменная не помечена static) имеет неопределенное значение.

Также, как правило, предупреждения в C никогда не следует игнорировать. Язык предполагает, что вы знаете, что делаете, и не имеет никаких средств защиты, которые есть у другого языка.

Другие вопросы по тегам