Подтвердить что ты не робот

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

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

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

int* ptr;

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

Строка:

int* ptr;

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

int* ptr = NULL;

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

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

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

Ответ 4

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

Object *ptr = new Object();

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

Ответ 5

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

Ответ 6

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

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

char * do_something (const char * one, const char * two);

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

Ответ 7

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

Ответ 8

int a,*ptr;

Теперь

print(ptr,*ptr)

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

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

    Вывод:

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

Ответ 9

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

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

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