2017-12-12 10 views
-1

私のプロジェクトで奇妙な動作が見られます。状況は次のとおりです。オブジェクトのコンストラクタへのポインタを指定すると、オブジェクトが破棄されます

  • 私はオブジェクトを持っています。 Victimに、ポインタ変数、コンストラクタ、デストラクタが含まれています。
  • 私は別のオブジェクトを持っています。Perpetratorを呼び出し、コンストラクタがVictimオブジェクトを受け入れ、ポインタ変数を内部の具体的な変数にコピーします。
  • Victim*を作成し、newでオブジェクトを作成した後、PerpetratorからPerpetrator(*victim)に渡してください。
  • Perpetratorのコンストラクタが終了すると、Victimのデストラクタが呼び出され、オブジェクトが削除されます。

問題は、poorが建設プロセス中に完全に破壊されたVictimの唯一のコピーです。最後にdelete poor経由でプログラムを整理すると、ダブルフリーエラーが発生します。

この動作は、C++ 98/11、GCC 4.8.5、7.x、およびLLVM CLANGでは一貫しているため、明確に定義する必要があります。この動作は何と呼ばれ、そのセマンティクスは何ですか?

私の理論は、constructorは具体的なオブジェクトを受け入れているためコピーされていると考えられますので、constructor/functionが完了すると破壊されます。

私はPoC||GTFOを賞賛するので、ここでのコードは次のとおりです。

明確化:それは単純化されたはるかに複雑なモデルが、非漏出性で適切に管理されたデータ構造複雑なので例は、意図的に書かれています。必要なビットをすべて削除すると、ひどく壊れたコードのように見えます。実際のコードでは、Victimは長い生きているデータストアであり、Perpetratorは前記データの処理に使用される中間記憶変数です。

#include <iostream> 

using namespace std; 

struct Victim 
{ 
    double* pointer; 

    Victim() 
    { 
    this->pointer = new double(42.2); 
    } 

    ~Victim() 
    { 
    cout << "Destructor of the Victim is called." << endl; 
    delete this->pointer; 
    } 

}; 

struct Perpetrator 
{ 
    double concrete; 

    Perpetrator (Victim victim) 
    { 
    concrete = *(victim.pointer); 
    } 
}; 


int main() 
{ 
    Victim* poor = new Victim(); 
    Perpetrator cruel(*poor); 

    cout << cruel.concrete << endl; 
} 

サンプル出力:

./destructor_test 
Destructor of the Victim is called. 
42.2 
Perpetrator (Victim victim)
+3

0/3/5の規則が壊れています。 'double * pointer;'はおそらく単に 'double value;'でなければならないので、メモリ管理はしません。 – Jarod42

+0

例はこのように意図的に書かれています。私は良質なコピーが、はるかに長く使用される予定のオブジェクトを破壊する可能性があることを示したかったのです。 – bayindirh

答えて

4

- 値によってオブジェクトを通過しています。電話が終了したらが破棄されてが破棄されたことを意味します。

実際には、newをまったく使用する必要はありません。これは:

int main() 
{ 
    Victim poor; 
    Perpetrator cruel(poor); 

    cout << cruel.concrete << endl; 
} 

同様に動作します。あなたは2つの構造と2つの破壊を見るでしょう。あなたの例が漏れているため、元のコードが表示しない2番目のコードです。参照することにより

+0

私は意図的に例が漏れているようにモデル化しました。私の例では、すでに完全に削除されているため、被害者を再削除することはできません。実際には漏れはしませんが、後には破壊の痕跡が残っています。したがって、Victimはこの例では複製されません。この例は、バニラの「値によるコピー」シナリオで複製されています。 – bayindirh

+0

@bayindirh - * "それは既に完全に削除されているので" *いいえ。 – StoryTeller

+0

はい、そうです。最後に 'delete poor'を追加すると、ダブルフリーエラーが発生します。 「犠牲者」の唯一のコピーは建設中に破壊されます。 – bayindirh

0

パス被害者:

struct Perpetrator 
{ 
    double concrete; 

    Perpetrator (Victim& victim) 
    { 
     concrete = *(victim.pointer); 
    } 
}; 

被害者が各一回&破壊を構築します。

0

これはあなたが欲しいものですか?

using namespace std; 

struct Victim 
{ 
    double* pointer; 

    Victim() 
    { 
    this->pointer = new double(42.2); 
    } 

    ~Victim() 
    { 
    cout << "Destructor of the Victim is called." << endl; 
    delete this->pointer; 
    } 
}; 

struct Perpetrator 
{ 
    double concrete; 

    Perpetrator (Victim *victim) 
    { 
    concrete = *(victim->pointer); 
    } 

    ~Perpetrator() 
    { 
    cout << "Destructor of the Perpetrator is called." << endl; 
    } 
}; 


int main() 
{ 
    Victim* poor = new Victim(); 
    Perpetrator cruel(poor); 
    cout << cruel.concrete << endl; 
    delete poor; 
} 

出力:被害者の 42.2
デストラクタが呼び出されます。
犯人のデストラクタが呼び出されます。

関連する問題