Неинициализированные указатели в коде

Я изучаю C++, и я узнал, что указатели, если оставить неинициализированные, могут указывать на случайные места в памяти и создавать проблемы, которые память может использоваться какой-то другой программой.

Теперь, если это так, мы никогда не должны иметь эту строку в любой части нашего кода:

int* ptr;

вместо этого мы должны иметь что-то вроде

int* ptr = NULL; //Is this going to avoid the problem

пожалуйста, предложите, потому что я видел первую строку (int* ptr;) во многих книгах, поэтому я получаю это сомнение. Если возможно, приведите также несколько примеров.

9 ответов


int* ptr = NULL; //Is this going to avoid the problem

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

главное преимущество ваше удобство для проверки ли ptr был или не был инициализирован ни к чему, т. е.:

 if (ptr != NULL)
 {
     // assume it points to something
 }

так как это довольно идиоматично, его довольно опасно не инициализировать указатель на NULL. Указатель будет инициализирован ненулевым значением мусора, которое на самом деле не указывает на что-либо реальное. Хуже всего, что проверка выше пройдет, что вызовет еще худшие проблемы, если так случится, что адрес в указателе-это память, к которой вы можете получить легальный доступ. В некоторых встроенных средах вы можете получить доступ к любой части памяти, поэтому вы можете случайно повредить случайные части памяти или случайные части вашего выполнения код.


всегда инициализируйте переменные.

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


строку:

int* ptr;

определенно не гарантируется инициализация значения указателя на что-либо в частности. Строка:

int* ptr = NULL;

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

конечно, все еще возможно, как сказал Дуг т., попытаться использовать этот указатель, не проверяя его, и поэтому он будет крушение все равно.

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


всегда лучше инициализировать указатель на NULL, если по какой-либо причине вы не можете инициализировать его во время объявления . Например:

Object *ptr = new Object();

обычно функция может проверить значение указателя на NULL, чтобы убедиться, что указатель был инициализирован ранее. Если вы явно не установили значение NULL, и оно указывает на случайное значение, то оно может быть разыменовано, вызывая segfault.


Это не проблема, пока она не используется.


если указатель не используется, компилятор просто проигнорирует его. Инициализация его в NULL-это безопасная вещь, имхо.

вы уверены, что не путаете с объявлением функции? Очень часто функция объявляется как

тип char* выполнить_действие(константный тип char* один константный тип char* двух);

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


C++ следуйте из C в том, что он не предназначен для безопасного; он предназначен для эффективного. Поэтому именно по этой причине автоматические переменные не инициализируются. Вы должны убедиться, что указатель не используется до его инициализации (хотя многие компиляторы предупредят вас, если вы не инициализируете свои переменные)


int a,*ptr;

Теперь

print(ptr,*ptr)

В приведенном выше коде возможны два случая:

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

    выход:

           ptr             *ptr
    eg.  0x400730       -1992206795
    
  2. это даст ошибку (сегментарная ошибка), если адрес по умолчанию в ptr-это адрес некоторой используемой памяти программы. Е. Г. если адрес переменной в памяти тоже 0x400730.


В C++ вы должны вообще избегать простых старых указателей. Стандартные классы библиотек, интеллектуальные указатели (до C++0x только в различных библиотеках, таких как Boost или Loki) и ссылки могут и должны использоваться в большинстве мест.

Если вы не можете избежать указателей, действительно предпочтительнее объявить их с инициализациями, которые в большинстве случаев не должны быть NULL, а фактическим целевым значением, потому что в C++ вы можете свободно смешивать объявления и выражения, поэтому вы можете и следует только объявить переменную в точке, в которой у вас есть значимое значение для нее.

Это не так с C, где вы должны использовать указатели много, и все переменные должны (или должны были до C99; я не совсем уверен) быть объявлены в начале области. Так много людей все еще имеют плохие привычки от C, которые не подходят для C++.