43

多次元配列を初期化する次の ANSI C コードがあるとします。

int main()
{
      int i, m = 5, n = 20;
      int **a = malloc(m * sizeof(int *));

      //Initialize the arrays
      for (i = 0; i < m; i++) { 
          a[i]=malloc(n * sizeof(int));
      }

      //...do something with arrays

      //How do I free the **a ?

      return 0;
}

を使用した後**a、メモリから正しく解放するにはどうすればよいですか?


【追記】(解決)

ティム (および他の人) の回答のおかげで、多次元配列からメモリを解放する関数を実行できるようになりました。

void freeArray(int **a, int m) {
    int i;
    for (i = 0; i < m; ++i) {
        free(a[i]);
    }
    free(a);
}
4

5 に答える 5

8

割り当てたものを正確に元に戻します。

  for (i = 0; i < m; i++) { 
      free(a[i]);
  }
  free(a);

最初にメモリを割り当てたときとはの順序でこれを行う必要があることに注意してください。free(a)最初に行った場合a[i]、解放された後にメモリにアクセスすることになり、これは未定義の動作です。

于 2009-11-14T10:16:51.573 に答える
4

配列を再度反復し、指定されたメモリの malloc と同じ数の解放を実行してから、ポインターの配列を解放する必要があります。

for (i = 0; i < m; i++) { 
      free (a[i]);
}
free (a);
于 2009-11-14T10:16:27.890 に答える
3

関数名を変更して、割り当て演算子を正確に逆の順序で記述すれば、問題ありません。

  //Free the arrays
  for (i = m-1; i >= 0; i--) { 
      free(a[i]);
  }

  free(a);

もちろん、まったく同じ逆の順序で割り当てを解除する必要はありません。割り当てられたメモリへのポインタを「忘れる」のではなく、同じメモリを一度だけ解放することを追跡する必要があります(a最初に解放した場合のように)。しかし、逆の順序で割り当てを解除することは、後者に対処するための良い経験です。

コメントでlitbが指摘しているように、割り当て/割り当て解除に副作用 ( C++ のnew/delete演算子など) がある場合、この特定の例よりも割り当て解除の後方順序が重要になることがあります。

于 2009-11-14T10:18:50.247 に答える
1

malloc() と free() を 1 回だけ呼び出します。

#include <stdlib.h>
#include <stdio.h> 

int main(void){
  int i, m = 5, n = 20;
  int **a = malloc( m*(sizeof(int*) + n*sizeof(int)) );

  //Initialize the arrays
  for( a[0]=(int*)a+m, i=1; i<m; i++ ) a[i]=a[i-1]+n;

  //...do something with arrays

  //How do I free the **a ?
  free(a);

  return 0;
}
于 2009-11-14T10:40:08.233 に答える