0

デストラクタが呼び出されるたびに、奇妙なメッセージが表示されました。私のプライベート変数の1つは動的に割り当てられた配列(int *member;)であるため、次のようにデストラクタを記述します。

ClassSet::~ClassSet(){delete []member;}

のデストラクタClassSetが呼び出されるたびに、エラーメッセージが表示されます。

WindowsがHw1.exeでブレークポイントをトリガーしました。

これは、ヒープの破損が原因である可能性があります。これは、Hw1.exeまたはロードされたDLLのいずれかにバグがあることを示しています。

これは、Hw1.exeにフォーカスがあるときにユーザーがF12キーを押したことが原因である可能性もあります。

クラス全体:

class ClassSet
{
  public:
    ClassSet(int n = DEFAULT_MAX_ITEMS);
ClassSet(const ClassSet& other);
ClassSet &operator=(const ClassSet& other);
~ClassSet();
  private:
    int size;
int *member;
 };

ClassSet::ClassSet(int n){
   size = n;
   member = new int[n];
}

ClassSet::ClassSet(const ClassSet& other){
    int i = 0;
    this->size = other.size;
member = new int [capacity];
while (i<size)
{
    this->member[i] = other.member[i];
    i++;
}
 }

 Multiset& Multiset::operator=(const Multiset &other)
 {
    if (&other == this){return *this;}
this->size = other.size;
int i = 0;
    delete [] member;
    member = new int[size];
while (i<other.size)
{
    this->member[i] = other.member[i];
    i++;
}
return *this;
}

このデストラクタの何が問題になっているのでしょうか。

4

4 に答える 4

4

または のいずれかを実装できませんでした (または正しく実装していませんClassSet::ClassSet(const ClassSet&)) ClassSet::operator=(const ClassSet&)

つまり、あなたは3 つのルールに違反しています。

ただし、最善の解決策は、それらを実装するのではなく、動的配列にスペースを割り当てる方法を変更することです。new[]andを使用する代わりに、delete[]そのメンバーを に置き換えてみてくださいstd::vector<>

于 2013-01-21T20:57:46.823 に答える
3

ヒープの破損は、多くの場合、事後に検出されます。デストラクタに関係している可能性があります。または、私が見たように、エラーが発生するヒープアクセスのかなり前に発生する可能性があります。

基本的に、「ヒープの破損が検出されました」とは、ヒープへの特定のアクセスで、ヒープの現在の状態が一貫していない/無効であると Windows が判断したことを意味します。少し前に何かがうまくいかなかった。

これらのバグを追跡するのは非常に困難です。ただし、ヒープ破損の一般的な原因の 1 つは、誤って何かを 2 回削除した二重削除です。これは、データがコードや設計にコピーされる方法に関するより深刻な問題を示している可能性があります。

これは、他の人が言ったように、動的メモリをコピーする適切なコピー コンストラクター/代入演算子がない場合に発生する可能性があります。「コピー」によってメモリが削除され、最初のクラスが再び削除されるため、二重の削除が発生します。

于 2013-01-21T20:58:21.240 に答える
1

実際のコードを投稿した場合、問題はここにあると思います:

ClassSet::ClassSet(const ClassSet& other){
    int i = 0;
    this->size = other.size;
    member = new int [capacity];  // <--- what is capacity?
    while (i<size)
    {
        this->member[i] = other.member[i];
        i++;
    }
}

capacityとの明らかな関係がない名前に基づいて、コピーされた配列のサイズを変更していother.sizeます。要素をコピーするループcapacityよりも小さい場合、ヒープが破損します。size

これが学術的な演習であると仮定すると、この問題を解決したら、例外の安全性を確保するために、このようなクラスで使用されるコピー/スワップ イディオムを調べる必要があります。

これが学術的な演習でない場合はstd::vector、ライブラリで提供されているまたはその他のコンテナーを確認する必要があります。

于 2013-01-21T22:34:28.277 に答える
0

この問題は非常に一般的です。デフォルトのコピーコンストラクタは、

ClassSet(const ClassSet& other) {
    size = other.size;
    member = other.member;
}

これに伴う問題は、インスタンスClassSetがコピーされるときに、元のインスタンスと新しいインスタンスの両方がへの生のポインタを保持することmemberです。両方のデストラクタが解放さmemberれ、発生している二重解放の問題が発生します。

例えば、

{
    ClassSet a
    ClassSet b(a); // assert(b.member == a.member)
} // At this point, both a and b will free the same pointer.

これを軽減するには、コピーを許可しないか、コピーする代わりにポインタを移動します。

于 2013-01-21T21:53:00.487 に答える