-1

この非常に単純なコードは、複雑な環境でワイルド ポインターが引き起こす種類の問題を示しています。

int main()
{
    int *a1 = new int;
    int *tmp = a1;
    delete a1;
    // Now, the tmp pointer is a wild pointer, it's dangerous.

    int *a2 = new int;
    delete tmp;
    // Now, the a2 pointer may be a wild pointer.
}

問題を検出または防止する方法はありますか? ここでスマートポインターが役立ちますか?

4

6 に答える 6

2

スマート ポインターを使用します。なぜだめですか?

あなたが持っているコードは無効であり、未定義の動作につながりますが、メモリ使用量に関しては C++ はそれほど厳密ではありません。それがその美しさです (そして呪い...)。リークの検出に役立つ外部ツールがありますが (あなたが示したようなケースではありません)、基本的には正しい構造を使用して正しくプログラミングすることになります。C++ には多くの柔軟性がありますが、正しく使用しないと厄介なバグが発生します。

于 2011-12-07T09:20:59.480 に答える
2

(少なくとも Linux では) valgrindのようなツールを使用して、そのようなバグを追跡できます。

また、 Boehm のガベージ コレクターを使用することもできます(メモリの解放を気にする必要はありません)。

一部の (IMHO 設計が不適切な) クラスは削除する必要があります (つまり、メモリの解放に加えてデストラクタで重要なことを行うため)、またはインスタンスへの手動ポインタを持つべきではありません。

RAIIについてもっと読んでください(これは C++ では非常に一般的ですが、普遍的なマントラではありません。たとえば、優れた Ocaml コードはそれに従っていません)。

また、スマート ポインターを使用することもできます。

于 2011-12-07T09:22:02.807 に答える
2

この問題の解決策は非常に簡単です。

コード内のリソースの所有権について常に明確にし、リソースの有効期間を管理するクラスを使用してこの所有権を強制します。

この場合 (ポインターを使用する必要があると仮定して)、私が提案する寿命は次のとおりです。

//Limit the scope of the variables to the minimum required:
{
    //a1 owns the pointer, so make it a `unique_ptr`
    std::unique_ptr<int> a1(new int);
    //tmp does not own the pointer, so make it a raw pointer
    //limit its scope to a shorter scope than a1
    int *tmp = a1.get();
}
//now the tmp pointer does not exist. It cannot be dangerous

//A similar strategy applies here
{
    //a2 owns the pointer
    std::unique_ptr<int> a2(new int);
}
//Again, a2 goes out of scope before any damage can occur.
于 2011-12-07T09:29:46.190 に答える
0

唯一の方法は、可能な限りコードの単体テストを行い、valgrind などのツールを使用してプログラムと単体テストを実行し、すべてのメモリ アクセスの問題を検出することです。

于 2011-12-07T09:22:19.643 に答える
0
int *a2 = new int;
delete tmp;
//now, the a2 pointer may be a wild pointer

いいえ、ポインターa2は有効な (解放されていない) 場所を指しています。

私の知る限り、ポインターがメモリ内の有効な (解放されていない) 場所を指しているかどうかを確認する方法はありません。

std::shared_ptr最初の例では、 a を使用して、割り当てられたメモリ ロケーションに対するこの共有所有権をモデル化できます。

于 2011-12-07T09:22:49.573 に答える
0

Cでは、あなたが足を撃つことを誰も妨げません。

C++ スマート ポインターなど、生活を楽にする方法があります: http://en.wikipedia.org/wiki/Smart_pointer#C.2B.2B_Smart_Pointers

valgrind などのツールはdeleteステートメントをオーバーライドし、メモリーを無効としてマークするため、後続のアクセスを検出して報告できます。たとえば0xDEADBEEF、デバッグ時に、削除されるはずのメモリをはみ出すような値で上書きすることが一般的です。これにより、削除されたメモリ領域にアクセスしていることをすぐに知ることができます。

本番環境では、通常、不要になったメモリへの書き込みをスキップする必要があるため、これらはデバッグ モードでのみ有効にする必要があります。

于 2011-12-07T09:23:28.207 に答える