0

私は多くのクラスがあるコードに取り組んでいます。コンストラクターでオブジェクトのさまざまな配列にメモリを割り当てています。しかし、すべてが大丈夫だと思っていたときに、奇妙なエラーが発生しました。例として、Points という名前のクラスがあり、データと呼ばれるポイントの double 配列があるとします。

さて、私は今すべてのコードを投稿しています:

class Points
{
      double *data;

      Points::Points()
      { 
           data = new double [C_NUMBER_OF_POINTS];
      }

      Points::~Points()
      {
           delete [] this->data;
      }
};

デバッグした後、エラーが this ポインターにあることがわかりましたが、その理由はわかりませんか? デストラクタは、オブジェクトが破棄されている間にデータを削除するために呼び出されますが、オブジェクトはまだメモリ内にあります。私の質問は、なぜこのようになっているのですか?

私が得ていたエラーは、基本的にメモリの取り扱いミスによるものです

HandTracker.exe の 0x778f15de で未処理の例外: 0x00000000: 操作は正常に完了しました。引用符

次のデストラクタを使用すると、このポインタの意味を削除するとエラーが修正されます

      Points::~Points()
      {
           delete []data;
      }

私の質問は、メモリリークを処理する方法についてではなく、このポインターに関連するこの特定の問題についてです。このエラーを発生させるこのポインターの背後にあるメカニズムは何ですか?

4

1 に答える 1

2

ほとんどの場合、コードのどこかでインスタンスをコピーしたかPoints、参照から別のインスタンスを作成しました。dataこれにより、同じポインターを持つクラスの 2 つのインスタンスが作成されました。最初のインスタンスが破棄されると、両方のインスタンスがポインタを持っていたオブジェクトが破棄されました。2 番目のオブジェクトがアクセスまたは破棄されたときに、オブジェクトが既になくなっていたため、問題が発生しました。

最善の解決策は、独自のデストラクタを持つ十分にテストされたクラスを使用して、デストラクタを持たないようにすることです。たとえば、この場合はstd::array (またはstd::vector ) です。これらのクラスには既に適切なデストラクタ、コピー コンストラクタ、およびコピー代入演算子があるため、これによりすべてが「魔法のように機能する」ようになります。

それ以外の場合は、デフォルト (メンバーごとのコピー/複製) が機能しないため、正しいコピー コンストラクターとコピー代入演算子があることを確認してください。3 のルールに関する James McNellis のコメントを参照してください。

これを試して:

Points::Points(const Points &a)
{
    data = new double[C_NUMBER_OF_POINTS];
    for (int i = 0; i < C_NUMBER_OF_POINTS; ++i)
          data[i] = a.data[i];
}

Points& operator=(const Points& a)
{ // The key is that this overrides the catastrophic default -- data=a.data;
     for (int i = 0; i < C_NUMBER_OF_POINTS; ++i)
           data[i] = a.data[i];
     return *this;
}
于 2012-08-08T02:37:57.447 に答える