web-dev-qa-db-ja.com

ダングリングポインターとは何ですか?

これはよくある質問ですが、私にとってはまだ新しいことです。

ダングリングポインターの概念がわからず、グーグルで回り、テストメソッドを作成してそれを見つけました。

これは宙ぶらりんのポインターなのだろうか?私が見つけたどのような例でも何かを返していたので、ここで同じようなことを試みています!

ありがとう!

void foo(const std::string name)
{
    // 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?
    new_foo(name.c_str());
}

void new_foo(const char* name)
{
    // print name or do something with name...   
}
41
code muncher

ダングリングポインターは、無効なデータまたは無効になったデータを指すポインターです。次に例を示します。

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を使用する場合、ポインターは有効なままです。

53
Jack

ダングリングポインターは、未割り当ての(既に解放された)メモリ領域を指す(非NULL)ポインターです。

上記の例は、文字列がnew_fooを介して変更されていない場合、正しいはずです。

10
Miklós Homolya

スタイルの問題として、私はぶら下がりポインターを「それが指し示したオブジェクトがもはや存在しないにもかかわらず、まだ存在するポインター」として説明します。

あなたの場合、ポインターnameは、それが指すオブジェクトよりも短い期間存在します。だから、ぶら下がることはありません。

一般的なC++クラス内では、ポインターはデストラクタ内で非常に短い期間ぶら下がります。これは、deleteステートメントがデストラクタの最後の}の前にあり、ポインタ自体が最後の}で存在しなくなるためです。これについて心配したくない場合は、例えばunique_ptr<T>T*ポインターは、unique_ptr::~unique_ptrデストラクタ内で非常に短時間ぶら下がりますが、これは完全に安全です。

4
MSalters

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はまだその場所をポイントしています。

4
Ashish Ahuja