2016-06-18 4 views
0

を与えると割り当てられたint型 `上で、私が持っている:`削除[]` * `` new`はC++大会の私の理解に続いてのmallocエラー

新しいブロックが AddBlockに作成され
class BlockRepresentation : public FPRepresentation 
{ 
    private: 
     class Block 
     { 
      public: 
       int id; 
       int fpDimensions; 
       int* position;  // pointers in question 
       int* blockDimensions; // pointers in question 

       ~Block(); 
     }; 
     std::vector<Block> all_blocks; 

    public: 
     BlockRepresentation(int count, int dimensions, int volumn[]); 
     void AddBlock(int id, int position[], int dimensions[]); 
     std::string ToGPL(); 
}; 

void BlockRepresentation::AddBlock(int id, int position[], 
     int dimensions[]) 
{ 
    Block newBlock; 

    newBlock.id = id; 
    newBlock.fpDimensions = fpDimensions; 
    newBlock.position = new int[fpDimensions];  // pointers in question 
    newBlock.blockDimensions = new int[fpDimensions]; // pointers in question 

    for (int i = 0; i < fpDimensions; ++i) 
    { 
     newBlock.position[i] = position[i]; 
     newBlock.blockDimensions[i] = dimensions[i]; 
    } 

    all_blocks.push_back(newBlock); 
} 

ので、私は、次のデストラクタがあります

BlockRepresentation::Block::~Block() 
{ 
    delete[] position; 
    delete[] blockDimensions; 
} 

をその後私は得る:

rep_tests(11039,0x7fff71390000) malloc: *** error for object 0x7fe4fad00240: pointer being freed was not allocated 

ここでは2つのポインタをdelete[]しないでください。コメントで指摘された

+2

[3のルール](http://en.cppreference.com/w/cpp/language/rule_of_three)を満たすコピーコンストラクタがありません。私の推測では、コピーのデストラクタ 'delete []'によってポインタが割り当てられていないということです。 –

+0

興味深いことに、私のテストがどのようにオブジェクトを使用しているかで、今実験して結果を得ることができます。 – Cescante

+0

今後の参考として、これをより良い質問にするにはどうすればよいですか?私はdownvotesのアカウントでそれを削除することが最善の行動だとは思わない? – Cescante

答えて

1

として、次の3つのルールに違反し、違反が非常に明白です:

{ 
    Block newBlock; 

    // snip 

    all_blocks.push_back(newBlock); 
} 

この関数が返す、newBlockオブジェクトがスコープの外に出ると、そのデストラクタがしますすべてのnew ed配列を削除してください。

しかし、このオブジェクトはpush_back()です。これは、オブジェクトのコピーをベクトルに構築します。 Blockはコピーコンストラクターを定義していないため、デフォルトのコピーコンストラクターは、new ed配列へのすべてのポインターのコピーを作成します。

何らかの形で、有効ではないポインタの逆参照を回避するか、その経験から生き残った場合、あなたはまだ森の中ではありません。これは、ベクトルが破棄され、そのBlockが破壊されると、それらのデストラクタはもう一度deletedと同じdeletedの同じ配列をdeleteにしようとします。

インスタントクラッシュ。

1

Blockデストラクタに問題はありません。それはあなたの2つのint *メンバ変数が指すメモリを解放するという仕事をしています。問題は、デストラクタが同じポインタ値で複数回呼び出されていることで、結果としてdouble-freeエラーが発生することです。

std::vectorがあなたのBlockオブジェクトのコピーを作成しますので、これは、std::vector<Block>でなり、そしてあなたのBlockオブジェクトが安全にコピーできませんエンティティ。

ポインタですBlockのメンバ変数がpositionblockDimensionsなので、この問題を軽減するための最も痛みのない方法はthis sample programによって示されるように、std::vector<int>代わりのint *を使用することです。

ただし、実際にint *を使用する場合は、ユーザー定義のコピーコンストラクタを実装する必要があります。さらに、ユーザー定義の代入演算子はコピーコンストラクタを補完します。これはRule of Threeと呼ばれています。

#include <algorithm> 
//... 
class Block 
{ 
    public: 
     int id; 
     int fpDimensions; 
     int *position; 
     int *blockDimensions; 

     Block() : position(nullptr), blockDimensions(nullptr), 
       id(0), fpDimensions(0) {} 
     ~Block() 
     { 
      delete [] position; 
      delete [] blockDimensions; 
     } 

     Block(const Block& rhs) : id(rhs.id), fpDimensions(rhs.fpDimensions), 
           position(new int[rhs.fpDimensions]), 
           blockDimensions(new int[rhs.fpDimensions]) 
     { 
     std::copy(rhs.position, rhs.position + fpDimensions, position); 
     std::copy(rhs.blockDimensions, rhs.blockDimensions + fpDimensions, 
        blockDimensions); 
     } 

     Block& operator=(const Block& rhs) 
     { 
     Block temp(rhs); 
     std::swap(temp.position, position); 
     std::swap(temp.blockDimensions, blockDimensions); 
     std::swap(temp.id, id); 
     std::swap(temp.fpDimensions, fpDimensions); 
     return *this; 
     } 
    }; 

ライブサンプルhereを参照してください。

は、我々は単にstd::vector<int>を使用するのではなく、std::vector内で使用する場合、正しく動作するようにBlockクラスを取得するために介してジャンプしなければならなかったフープのすべてを参照してください?

関連する問題