Что такое висячий указатель
Я знаю, что это довольно распространенный вопрос, но все же новый для меня!
Я не понимаю понятия висячего указателя, искал его и писал методы тестирования
найти... Я просто удивляюсь, что это болтающийся указатель? Как и любой пример, который я нашел, возвращался
что-то, здесь я пытаюсь что-то подобное!
Спасибо!
void foo(const std::string name)
{
new_foo(name.c_str()); ///// will it be Dangling pointer?!, with comments/Answer
///// it could be if in new_foo, I store name into Global.
///// Why?! And what is safe then?
}
void new_foo(const char* name)
{
... print name or do something with name...
}
Ответы
Ответ 1
Висячий указатель - это указатель, указывающий на недопустимые данные или данные, которые больше недействительны, например:
Class *object = new Class();
Class *object2 = object;
delete object;
object = nullptr;
// now object2 points to something which is not valid anymore
Это может произойти даже в выделенных стеке объектах:
Object *method() {
Object object;
return &object;
}
Object *object2 = method();
// object2 points to an object which has been removed from stack after exiting the function
Указатель, возвращаемый c_str
, может стать недействительным, если строка будет изменена впоследствии или уничтожена. В вашем примере вы, кажется, не изменяете его, но поскольку неясно, что вы собираетесь делать с const char *name
, это невозможно узнать, что ваш код по своей сути безопасен или нет.
Например, если вы где-то сохраняете указатель, а затем соответствующая строка уничтожается, указатель становится недействительным. Если вы используете const char *name
только в области new_foo
(например, для целей печати), то указатель останется в силе.
Ответ 2
Висячий указатель - это (не-NULL) указатель, который указывает на нераспределенную (уже освобожденную) область памяти.
Вышеприведенный пример должен быть правильным, если строка не изменяется через new_foo.
Ответ 3
В качестве стиля я объясняю висячий указатель как "указатель, который все еще существует, хотя объект, на который он указал, больше не существует".
В вашем случае указатель name
существует для более короткого периода, на который указывает объект. Поэтому он никогда не болтается.
Внутри обычных классов С++ указатели на короткое время болтаются внутри деструкторов. Это потому, что оператор delete
находится перед последним }
деструктора, а сам указатель перестает существовать в последнем }
. Если вы не хотите беспокоиться об этом, используйте, например, unique_ptr<T>
. Указатель T*
будет зависеть в течение короткого времени внутри деструктора unique_ptr::~unique_ptr
, который совершенно безопасен.
Ответ 4
Взято из здесь. Хотя, даже если это для C, для С++ это то же самое.
Указатель обманывания
Если какой-либо указатель указывает адрес памяти любой переменной, но после того, как какая-либо переменная удалилась из этой ячейки памяти, пока указатель все еще указывает на такую ячейку памяти. Такой указатель известен как оборванный указатель, и эта проблема известна как проблема оборванных указателей.
Сначала
![введите описание изображения здесь]()
В дальнейшем
![введите описание изображения здесь]()
Пример
#include<stdio.h>
int *call();
int main(){
int *ptr;
ptr=call();
fflush(stdin);
printf("%d",*ptr);
return 0;
}
int * call(){
int x=25;
++x;
return &x;
}
Выход будет мусором, поскольку переменная x является локальной переменной. Его область действия и время жизни находятся внутри вызова функции, поэтому после возвращения адреса переменной x x стал мертвым, а указатель все еще указывает, что ptr все еще указывает на это местоположение.
Ответ 5
Висячий указатель и проблема с висячим указателем
Если какой-либо указатель указывает адрес памяти любой переменной, но после удаления какой-либо переменной из этой ячейки памяти, в то время как указатель все еще указывает на такую ячейку памяти.
Этот указатель вызывается как обвисший указатель, а проблема, возникающая в это время, называется проблемой оборванных указателей.
Вот несколько примеров: Ошибка указателя поворота и висячего указателя