演習として、手動ポインターを使用して、サイズ変更可能な配列クラス (std::vector) を作成しています (スマート ポインターの使用を開始する前に、それらがどのように機能するかを知りたいため)。ただし、Valgrind は checkMax() 関数でメモリ リークを報告します。
template <typename T>
class Array{
public:
Array() : len(0),maxLen(1){
array=new T[maxLen];
// ........
}
Array(unsigned length, T&content=0) : len(length),maxLen(length*2){
array=new T[maxLen];
//..............
}
~Array(){
//delete[] array;
}
//..............
void push_back(const T& content){
checkMax();
// do stuff...
}
private:
T* array;
unsigned int len;
unsigned int maxLen;
..
void checkMax(){
if(len==maxLen){
//allocate more memory for the array
maxLen*=2;
T*temp=new T[maxLen]; // ------------- MEMORY LEAK HERE -------------
for(unsigned int i=0; i<len; i++){
temp[i]=array[i];
}
delete [] array;
array=temp;
}
}
};
ここでは、メモリ関連のコードのみを掲載しました。
指定した行で Valgrind がメモリ リークを報告している理由がわかりません。古い配列の内容を拡大された配列にコピーした後、2行後に古い配列を削除します。
また、デストラクタで delete[] 関数のコメントを外すと、例外が発生 double free or corruption
し、Valgrind が無効な削除 (再削除を意味する) を報告するので、完全に当惑します。何か案は?
編集: 早い返信ありがとうございます! コメントを読んだ後、問題はクラスにあるのではなく、Array クラスを引数として呼び出していた別の関数にあることがわかりました。この関数の呼び出しを削除し、クラスに削除呼び出しを追加すると、メモリ リークは発生しません。これが私の機能です:
template <typename T>
void printContents(Array<T> ar){
for(unsigned int i=0; i<ar.size(); i++){
cout<<"Content at i in array = " << ar.at(i) << endl;
}
}
Rule of Three (chris に感謝) と Grizzly が投稿した回答を読んだ後、delete[] が無効である理由がわかりました。コピー コンストラクターをオーバーロードしていないため、浅いコピーが発生したため、配列ポインターがar のポインターに割り当てられ、ar がスコープ外のときに delete[] が呼び出され、メインで削除が行われました。機能無効。したがって、私は例外を受けていました。削除を削除すると、配列は明らかに割り当てられたままになり、メモリ リークが発生します。
助けてくれてありがとう、グリズリーの答えを正しいと投票しました。