0

ポインタを削除するためにキーワード「delete」を使用しない場合のメモリリークの正式な意味を知っているだけです。しかし、次のように実行すると、なぜリークの可能性があるのでしょうか?

void k()
{
vector<m*>p;
:
:
:
} 

私が知る限り、ポインタの削除はコンパイラ自体によって自動的に行われるので、最後にポインタを削除する必要は本当にありますか?

4

8 に答える 8

3

私の知る限り、ポインタの削除はコンパイラ自体によって自動的に行われます

いいえ、ちがいます。以下は漏れです。

vector<m*>p;
p.push_back(new m);

自分でメモリを削除する必要があります。

delete p[0]; //in this case

クリーンな代替手段は、スマート ポインターを使用することです。

vector<std::shared_ptr<m> > p;
于 2012-12-13T09:10:27.423 に答える
3

これは、何を入れるかによって異なりますp。他の場所で管理されているもの (または動的に割り当てられていないもの) へのポインタを格納するだけであれば、リークはありません。 の内容はvectorデストラクタによってクリーンアップされます。

ただし、次のようなことを行い、 before exitsの要素をp.push_back(new m);呼び出さない場合は、実際にメモリ リークが発生しています。(ポインター)の内容は、そのデストラクタによってクリーンアップされます。ポインタが指すメモリはそうではありません。deletepkvector

于 2012-12-13T09:13:19.270 に答える
2

最初の質問に答えるために: メモリ管理エラーには、関連しているが異なる概念が 2 つあります。私は、一般的なメモリ デバッガである Valgrind で使用される用語が好きです。

  • まだ到達可能なメモリ: これは厳密にはリークではなく、プログラマの怠慢です。汚れていますが、必ずしも問題ではありません。これは、クリーンアップできたはずのものをクリーンアップすることを気にしない場合に発生します。

    int main()
    {
        int * p = new int[100];
    }
    
    // memory at p is still reachable
    

    このようなコードでは、「まだ到達可能な」割り当ては通常、プログラムの最後まで使用され、クリーンアップする唯一の適切なポイントは最後になります。

  • 間違いなく失われたメモリ: これはあなたの本当のリークです. この状況は、動的に割り当てられたメモリへの参照がすべて失われた場合に発生します。つまり、原則として、それらのリソースを解放する方法はありません。これは重大なプログラミング エラーです。ループ内、または任意の回数呼び出されたものでメモリ リークが発生した場合、プログラムは長時間実行された後、おそらく OS の残りの部分がしばらく使用できなくなる前に停止する可能性があります。典型的なコードは次のようになります。

    int foo()
    {
        int * p = new int[100]();
        return p[20] + 2;
    }   // leak: We lost track of the memory at p
    
    int main()
    {
        for (std::string line; std::getline(std::cin, line); )
        {
            int * q = new int[line.length() + 1];
            q[0] = foo();  // leak 1
        }                  // leak 2: lost track of the memory at q
    }
    

上記の状況はすべて、13 世紀に最初に策定されたメモリ管理の基本規則に違反しています。

CPU、私をあなたのコードの道具にしてください。
あるところはmalloc書きましょうfree
あるところにnewdelete
あるところにnew[]delete[]
入る

当然の結果として、 C++ メモリ管理のゴールデン ルールを推測できます。これにより、メモリ管理のバグのリスクが劇的に減少します。

new使用しないでくださいdelete。生のポインターを使用しないでください。

要点は、生のポインタは可能なポインティに関する所有権情報を持たないということです。したがって、生のポインターだけに基づいて、クリーンアップを行う必要があるかどうか、およびその方法を決定することは不可能です。これはコードの問題でもあります。答えは単純に「場合による」です。

于 2012-12-13T09:29:30.490 に答える
2

ベクトルの内容 ( s )割り当てると仮定すると、リークを回避したい場合は、関数を終了する前に自分で実行する必要があります。ベクトル コンテンツの自動削除は、コンテンツがオブジェクトであり、動的に割り当てられたオブジェクトへのポインタではない場合にのみ機能します。m*newdelete

あなたができることは、に置き換えることm*ですstd::unique_ptr<m>。これで、スマート ポインター自動的に実行deleteされるようになり、何もする必要はありません。

vector<std::unique_ptr<m>>p;

あるいは、これも安全です。値で保存しているため、関数が終了すると、内容はベクトル デストラクタによって自動的に破棄されます。

vector<m>p;
于 2012-12-13T09:10:09.537 に答える
0

表面的な答えは「いいえ」です。スニペットにメモリを割り当てていないため、リークが発生することはありません。より使いやすい答えは次のとおりです。それは、の役割と、vector何を入れているかによって異なります。

まず、型mに値のセマンティクスがあり、コピー可能である場合は、vector<m>ではなくを使用する必要がありvector<m*>ます。そしてもちろん、リークの可能性はありません(正しくvector<m> 実装したと仮定して)。m

ポインターのベクトルを使用する最も一般的な理由は、少なくとも私が携わったアプリケーション ドメインでは、エンティティ オブジェクト間のナビゲーションです。各エンティティ オブジェクトは、独自の有効期間を管理するか、(あまり頻繁ではありませんが) 有効期間を管理する他のエンティティ オブジェクトに属します。したがって、リークのリスクはありませんがダングリング ポインターの非常に重大なリスクがあります。オブジェクトを指すオブジェクトの有効期間が終了したら、そのオブジェクトへのポインターがベクトルから削除されていることを確認する必要があります。(これは通常、オブザーバー パターンの変形を使用して行われます。)

ポインターのベクトルを使用するもう 1 つの理由は、含まれているオブジェクトがポリモーフィックであるか、コピーするのに大きくてコストがかかるためです。このような場合、含まれているオブジェクトにポインターが含まれていない場合、または循環が不可能であることを証明でき、ポイントされたオブジェクトに重要な内部動作がないことを証明できる場合 (したがっての使用は非常に限られていますthis)、のコレクションstd::shared_ptr<m>; 実際には、Boost のポインター コンテナーがおそらくより良い解決策です (そして のリスクを回避しますstd::shared_ptr)。ソリューションと Boost のポインター コンテナーの両方 shared_ptrで、ベクター内のすべての要素が動的に割り当てられる必要があります。

于 2012-12-13T11:38:19.443 に答える
0

ベクトル自体は問題ありません。独自のメモリを自動的かつ正しく管理します。

したがって、答えはそのベクトルに何を入れるかによって異なります。ヒープに割り当てられたオブジェクトへのポインターを配置する場合、それらのオブジェクトを使い終わったときにそれらのオブジェクトの割り当てを解除するのはあなたの責任です。ベクトルはそれをしません。

これを怠ると、メモリ リークが発生します。

于 2012-12-13T09:11:05.320 に答える
0

そのベクトルから要素を削除する場合 ( resizeeraseまたはを使用)、それが で割り当てられてclearいると仮定すると、演算子は使用されません。したがって、メモリリークが発生します。ただし、これらのポインタがスタック上の変数を指している場合、メモリ リークは発生しません。m*newdelete

編集: ベクトルから要素を消去する前に要素を削除できますが、サイズ変更またはクリアを呼び出すと、すべてを削除することはほとんどありません (クリアする前にループして削除しない限り)。

于 2012-12-13T09:11:41.487 に答える
0

ベクトルが削除されても、ベクトル内のポインターは削除されません。あなたは使用することができます

vector<shared_ptr<m>> p

プログラムの他の部分とポインターを共有する場合。

于 2012-12-13T09:15:42.810 に答える