Неинициализированные указатели в коде - PullRequest
30 голосов
/ 03 мая 2011

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

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

int* ptr;

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

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

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

Ответы [ 8 ]

36 голосов
/ 03 мая 2011
int* ptr = NULL; //Is this going to avoid the problem

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

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

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

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

9 голосов
/ 03 мая 2011

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

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

6 голосов
/ 03 мая 2011

Строка:

int* ptr;

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

int* ptr = NULL;

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

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

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

2 голосов
/ 03 мая 2011

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

Object *ptr = new Object();

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

1 голос
/ 16 января 2016
int a,*ptr;

сейчас

print(ptr,*ptr)

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

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

    Вывод:

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

1 голос
/ 03 мая 2011

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

1 голос
/ 03 мая 2011

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

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

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

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

0 голосов
/ 03 мая 2011

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

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

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

...