1

そのため、ノード クラスのインスタンスを保持するために、スタックのような機能 (LIFO) を備えたリンク リスト クラスを構築しています。

enum Sides{NorthWest=0, North=1, NorthEast=2, West=3, East=4, SouthWest=5, South=6, SouthEast=7};

class Node
{
    public:
    Node(position2df pos, int id):nextNode(NULL)
    {
        position=pos;
        ID=id;
    }
    ~Node(){}

    position2df getPosition(){return position;}
    int getID(){return ID;}

    void setPeripheralID(Sides side, int id){peripheralID[side]=id;}
    int getPeripheralID(Sides side){return peripheralID[side];}

    Node *nextNode;

    private:
    position2df position;
    int ID;
    int peripheralID[8];
};

class NodeList
{
    public:
    NodeList()
    {
        root=NULL;
        end=NULL;
    }
    ~NodeList(){}

    /// Function for adding elements to the list.
    void push(position2df pos, int id)
    {
        if(root==NULL)
        {
            root=new Node(pos, id);
            end=root;
        }
        else
        {
            Node *newend=new Node(pos, id);
            end->nextNode=newend;
            end=end->nextNode;
        }
    }

    /// Function for removing objects from the list.
    Node *pop()
    {
        slider=root;
        Node *previous;
        Node *next=slider;

        for(previous=NULL; next!=NULL; next=slider->nextNode)
        {
            previous=slider;
            slider=next;
        }

        delete slider;
        end=previous;
        cout << "Can still access deleted object: " << (*slider).getID() << endl;

        return end;
    }

    private:
    Node *root;
    Node *end;
    Node *slider;
};

NodeList::Node *pop()関数 (最後の要素を削除し、前の要素をリストの最後としてリセットすることを目的としています) で、(ポインター名) スライダーが指すインスタンスで delete を呼び出しますNode class。ただし、削除した後でも、インスタンスにアクセスしてそのメンバーを出力できます。問題があるかどうかはわかりませんが、インスタンスには、削除時にそれを指す 3 つの異なるポインターがあります。彼らです:

  • ノード *スライダー;
  • ノード *end;
  • 前のクラス インスタンスの Node::Node *nextNode;

この時点で、質問が適切であると思います:D

削除した後もインスタンス メンバーにアクセスできる場合、適切に削除されたかどうかを確認するにはどうすればよいですか?

私のコードはメモリリークを引き起こしますか?

究極の質問は次のとおりだと思います。私は何か間違ったことをしていますか?

PSposition2df; vector2df;ここには、Irrlicht Game Engine からの変数がいくつかあります ( )。混乱を避けるために、それを指摘したかっただけです。

この投稿が漠然としていたり​​、不明確だったりした場合はご容赦ください。オンラインで質問するのは得意ではありません。

4

6 に答える 6

3

削除した後もインスタンス メンバーにアクセスできる場合、適切に削除されたかどうかを確認するにはどうすればよいですか?

ランタイム ライブラリを信頼するだけですdelete。メモリが不要になったことをシステムに伝えると、メモリは放棄されます。メモリはもはや自分のものではありません。システムは、再配分するために使用可能なメモリと一緒にそれをカウントするため、要求に応じてプログラムの他の部分に割り当てることができます。そのメモリには引き続きアクセスでき、あきらめる前にそこにあったものを見つけることさえできますが、それは未定義の動作です。

私のコードはメモリリークを引き起こしますか?

いいえ、割り当てたメモリを解放するためです。

究極の質問は次のとおりだと思います。私は何か間違ったことをしていますか?

はい - 割り当て解除されたオブジェクトのメモリへのアクセスは間違っています (未定義の動作)。それ以外は問題ないようです。

于 2013-04-19T10:47:51.687 に答える
1

削除後にアクセスされた場合、それはリークではありませんが、未定義の動作です: 別名、発生を待っているクラッシュ。

于 2013-04-19T10:45:37.133 に答える
0

削除した後もインスタンス メンバーにアクセスできる場合、適切に削除されたかどうかを確認するにはどうすればよいですか?

メモリを呼び出しdeleteた後、あなたのものではなくなり、オブジェクトは削除されたと見なされます

私のコードはメモリリークを引き起こしますか?

いいえ、呼び出していない場合deleteはリークになりますが、ここでは以前に割り当てたメモリを解放したので、問題ありません。

究極の質問は次のとおりだと思います。私は何か間違ったことをしていますか?

はい、呼び出した後delete、オブジェクトがまだあると想定しないでください。これは未定義の動作です

于 2013-04-19T10:58:32.657 に答える
0

それらを削除した後でもクラス インスタンスにアクセスできるのはなぜですか?

できません。

オブジェクトを含むメモリへのポインターがまだある場合は、その残りの部分にアクセスできる場合とできない場合があります。または、オブジェクトが削除されてから作成された別の無関係なオブジェクトである可能性があります。運が良ければ、メモリがマップされていない可能性があり、エラーを指摘するわかりやすいセグメンテーション フォールトが表示されますが、これは通常、非常に大きなオブジェクトでのみ発生します。

つまり、削除されたオブジェクトへのポインターを逆参照すると、未定義の動作が発生します。

適切に削除されたかどうかを確認するにはどうすればよいですか?

プログラムがいつそれを削除したかを知り、その後ダングリングポインターを使用しないようにします。生のポインターを使用して直接呼び出す場合、これは非常deleteに注意が必要です。そのため、通常、コンテナーやスマート ポインターなどの RAII 型を使用して動的メモリを管理する必要があります。

私のコードはメモリリークを引き起こしますか?

私が見る限り、pop関数にリークはありません。スマート ポインターを使用した場合は、より明確に正確にすることができます。

デストラクタは何も削除しないので、リストの内容を削除する責任が他にない限り、リストが破棄されたときに残っているものはすべてリークします。

究極の質問は次のとおりだと思います。私は何か間違ったことをしていますか?

リークを修正するためにデストラクタを追加した場合は、リストをコピーする場合に二重削除を防ぐために、コピー コンストラクタとコピー代入演算子も追加 (または削除) する必要があります。これは3 つのルールとして知られることもあり、リソース管理クラスを作成するときに非常に重要です。スマート ポインターを使用する場合は、スマート ポインターがすべての処理を行い、より単純な "Rule of Zero" に従うことができます (つまり、コンパイラーにこれら 3 つのことを生成させるだけです)。

于 2013-04-19T11:01:10.647 に答える
0

new と delete を使用するときは、動的メモリを操作しています。つまり、メモリ ブロックを予約するか解放します。解放すると、自由に使用できるという注釈が付けられるだけなので、必要に応じて再利用できます。ただし、プログラムは、そのメモリ領域をクリアするための労力を一切費やしません。

解放されたメモリ領域へのポインタを持つことは可能であり、そこからデータを読み取ることができるかもしれませんが、そこにあるデータは、プログラムがより多くのメモリを予約する必要があるときにいつでも置き換えられる可能性があるため、注意してください。

解放されたメモリ領域へのアクセスは、常に危険であり、プログラムのクラッシュやさらに悪いことに誤動作を引き起こす可能性があります。

于 2013-04-19T10:53:41.907 に答える
0

削除されたオブジェクトはすぐには上書きされません。それらが存在するメモリ領域は、単に「自由に使用できる」とマークされています。メモリが再割り当てされ、他の目的のために初期化される前に上書きされることはありません。

いつ、なぜこれが発生するかを制御することはできないため、メモリを削除した後は絶対にアクセスしないでください。これを確実にするために、削除されたオブジェクトを指すすべてのポインターは、削除する前に null に設定する必要があります。

于 2013-04-19T10:47:42.930 に答える