2013-08-01 4 views
32

Я знаю, что это довольно распространенный вопрос, но все же новый для меня!Что такое свисающий указатель

Я не понимаю понятия висячего указателя, искал его и писал методы тестирования , чтобы найти его ... Я просто удивляюсь, разве это висячий указатель? Как и любой другой пример, я возвращал что-то, здесь я пытаюсь что-то подобное! Спасибо!

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... 
} 
+0

* «?! Это будет Висячие указатель с комментариями/Ответ это» * - Нет, это не так. В первом примере нет обвисшего указателя. То, что вы там делаете, прекрасно, на 100% безопасно и правильно. –

+0

Я не вижу, как вы можете иметь * висящий указатель * ... без указателя *. –

+0

@ TheOtherGuy Я имею в виду, no const char * ... переносящий такой же const std :: string –

ответ

38

висячей указатель является указателем, который указывает на недействительные данные или данные, которые не является действительным больше, например:

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 (например, для печати), то указатель останется в силе.

+0

Вы также можете добавить, что пример OP не обманывает – Angew

+0

IIRC, если вы изменяете содержимое строки, тогда вы аннулируете указатель, возвращаемый 'c_str()', поэтому он * может * считаться зависающим. – Jack

+0

Но строка не изменяется. И нет никакой возможности для его юридической модификации даже в многопоточном приложении. –

10

Висячий указатель - это (не-NULL) указатель, который указывает на нераспределенную (уже освобожденную) область памяти.

Приведенный выше пример должен быть правильным, если строка не изменяется с помощью new_foo.

+0

... подчеркивание «* уже освобождено *»! – alk

+0

@ Miklós Homolya его "const" .. что вы имеете в виду изменить в new_foo ?! –

+0

Это использование функции «const» (компилятор), которая может быть преодолена с помощью const_cast. Проблема заключается в том, как получить стандартную совместимость - ссылку на переменную «имя» стека, поскольку код функции «foo» уже задан. –

2

В качестве стиля я объясняю висячий указатель как «указатель, который все еще существует, хотя объект, на который он указал, больше не существует».

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

Внутри обычных классов C++ указатели на короткое время болтаются внутри деструкторов. Это потому, что инструкция delete находится перед последним } деструктора, в то время как сам указатель перестает существовать на последних }. Если вы не хотите беспокоиться об этом, используйте, например, unique_ptr<T>. Указатель T* будет очень долго болтаться в деструкторе unique_ptr::~unique_ptr, который совершенно безопасен.

2

Взято из here. Хотя, даже если это для C, это то же самое для C++.

оборванными Указатель

Если какой-либо указатель указывает на адрес памяти любой переменной, но после некоторой переменной удалила из этой ячейки памяти, в то время как указатель все еще указывает такую ​​ячейку памяти. Такой указатель известен как оборванный указатель, и эта проблема известна как проблема оборванных указателей.

Первоначально

enter image description here

Позже

enter image description here

Пример

#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 все еще указывает на это местоположение.

-2

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

Этот указатель называется обвисшим указателем, и проблема, возникающая в это время, называется проблемой оборванных указателей.

Вот некоторые примеры: Dangling Pointer and dangling pointer problem

Смежные вопросы