2017-01-10 21 views
1

私の質問は、デストラクターが私の一時配列のメモリを解放しないのはなぜですか? Valgrindは私のコンストラクタでnew演算子を使用したが、その後はメモリを削除しなかったことを伝えている。 delete tempと書いてみると、Valgrindのサイズの読み込みが正しくないなど多くのエラーがあります。ここで何が起こっているのか教えてもらえますか?なぜデストラクターは配列メモリを解放しませんか?

array_xyz(const int r, const int c, double **arg_array) { 

    rows = r; 
    cols = c; 
    array_xyz *temp = new array_xyz(); 
    temp->arr = new double *[rows]; 
    temp->rows = r; 
    temp->cols = c; 
    arr = new double *[rows]; 

    for (int i = 0; i < rows; i++) { 
     arr[i] = new double [cols]; 
     temp->arr[i] = new double [cols]; 
    } 

    for (int j = 0; j < rows; j++) { 
     for (int k = 0; k < cols; k++) 
      temp->arr[j][k] = arg_array[j][k]; 
    } 

    arr = temp->arr; 
    //delete temp; -> doesn't work, valgrind tells that I free memory twice 
} 

array_xyz() { 
    rows = 0; 
    cols = 0; 
    arr = NULL; 
} 

~array_xyz() { 
    for (int i = 0; i < rows; i++) 
     delete []arr[i]; 
    delete []arr; 
} 
+1

メモリを解放するようにC++ランタイムに依頼しただけであるため、すぐにOSに解放されるわけではありません(ページ内の他の割り当ても解放する必要があります)。 –

+2

1)コンストラクタが終了すると 'temp'は解放されません。 2) 'arr = temp-> arr;'は 'arr = new double * [rows];によって確保されたメモリへのポインタを上書きしないで最初に解放します。 3)「temp」が必要なのはなぜですか? –

+0

'arr'は、構築しているオブジェクトのデストラクタで最終的に削除されるので、(同じアドレスを持つ)' temp'を削除するとデストラクタの 'free'とその間のすべてのアクセスが無効になります。 –

答えて

2

この文の後に同じに

arr = temp->arr; 

両ポインタarrtemp->arrポイントがメモリの拡張。このsatetment

delete temp 

を追加した場合

は、クラスarray_xyzのデストラクタは、メモリのこの範囲を解放(およびエクステントは、動的に割り当てられた配列の要素によって指されます)。また、自身のポインタarrが同じメモリを指しているため、作成されたオブジェクトのデストラクタも同じエクステントを削除します。したがって、同じメモリエクステントを2回解放する試みがあります。

なぜポインタtempが指す中間的に動的に作成されたオブジェクトを使用しているのかは不明です。コンストラクタの読者だけを混乱させる完全な冗長コードです。

1

ありがとうございました。私はarg_arrayからarrに値をコピーしたかったので、そこにはtempも必要ないという良い点がありました。あなたは両方のarr(およびそのすべての行)とtemp_arr(およびそのすべての行)を割り当てる

array_xyz(const int r, const int c, double **arg_array) { 

    rows = r; 
    cols = c; 
    arr = new double *[rows]; 

    for (int i = 0; i < rows; i++) { 
     arr[i] = new double [cols]; 
    } 

    for (int j = 0; j < rows; j++) { 
     for (int k = 0; k < cols; k++) 
      arr[j][k] = arg_array[j][k]; 
    } 

} 
+0

脇に、2番目のループで割り当てを統合することができます。 2回繰り返す必要はありません。 –

5

はここソリューションです。その後、arr=temp_arr;を実行します。 temp_arrの値をarrにコピーしません。代わりに、arrtemp_arrと同じアドレスを指すようにします。 arrに割り当てられたメモリ全体が孤立しています(ポインタが存在しないため、解放することはできません)。 temp_arrを削除すると、メモリ内の同じ場所を指すように、arrが自動的に削除されます。

関連する問題