6

メモリ リークを発生させずに int マトリックスを生成する際に問題が発生しています。read_matrix() を使用して、特定の (グローバル) マトリックスを動的に任意のサイズにできるようにしたいと考えています。しかし、後でメモリを解放できるようにしたいのです。したがって、私のメイン メソッドでは、メモリが割り当てられていないため、2 番目の printf はバス エラーになるはずです。これを作成するにはどうすればよいですか?

int**       first_matrix;
int**       second_matrix;
int**       result_matrix;

int** read_matrix(int size_x, int size_y)
{
    int** matrix;
    matrix = calloc(size_x, sizeof(int*));
    for(int i = 0;i<size_x;i++) {
        matrix[i] = calloc(size_y, sizeof(int));
    }
    for(int i = 0;i<size_x;i++) {
        for(int j = 0;j<size_y;j++) {
            matrix[i][j] = i*10+j;
        }
    }
    return matrix;
}

int main(int stackc, char** stack)
{
    first_matrix = read_matrix(10,10);
    printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
    free(*first_matrix);
    free(first_matrix);
    printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
}
4

7 に答える 7

9

メモリが解放されたからといって、アクセスできないわけではありません。もちろん、解放された後にアクセスするのは非常に悪い考えですが、それがあなたの例で機能する理由です。

他の配列ではなく、free( *first_matrix )free のみであることに注意してください。first_matrix[0]最後の配列を示す何らかのマーカーが必要になる場合があります (外側の配列を解放するときに、割り当てた内側の配列の数が常にわかっている場合を除く)。何かのようなもの:

int** read_matrix(int size_x, int size_y)
{
    int** matrix;
    matrix = calloc(size_x, 1+sizeof(int*)); // alloc one extra ptr
    for(int i = 0;i<size_x;i++) {
        matrix[i] = calloc(size_y, sizeof(int));
    }
    matrix[size_x] = NULL; // set the extra ptr to NULL
    for(int i = 0;i<size_x;i++) {
        for(int j = 0;j<size_y;j++) {
            matrix[i][j] = i*10+j;
        }
    }
    return matrix;
}

次に、それらを解放するとき:

// keep looping until you find the NULL one
for( int i=0; first_matrix[i] != NULL; i++ ) {
    free( first_matrix[i] );
}
free( first_matrix );
于 2008-09-19T21:18:00.320 に答える
2

各行を個別に解放する必要があります。


void free_matrix(int **matrix, int size_x)
{
    for(int i = 0; i < size_x; i++)
        free(matrix[i]);
    free(matrix);
}
于 2008-09-19T21:14:08.177 に答える
1

メモリを解放しても、それがなくなるわけではありません。別の割り当てが同じメモリのチャンクを取得する可能性があることを意味します。あなたが入れたものは、何か他のものが上書きされるまでそこに残ります。

また、割り当てたものすべてを解放しているわけではありません。ポインターの配列と最初の行のみを解放しています。しかし、すべてを正しく解放したとしても、同じ効果が得られます。

「バスエラー」を作成したい場合は、プロセスに属していないメモリを指す必要があります。そもそも、なぜそれをしたいのですか?

于 2008-09-19T21:15:21.997 に答える
0

行列の最初の行と行のリストを解放しているため、メモリ リークが発生していますが、1 から n 番目の行は解放されていません。ループで free を呼び出す必要があります。

ただし、いくつかの代替手段があります。 - sizeof(int*)行 + 行cols*sizeof(int) バイトを割り当て、最初のバイトを行ポインターに使用します。そうすれば、解放するメモリのチャンクが 1 つだけになります (アロケータでも簡単です)。行数を含む構造体を使用します。次に、行リストを完全に回避できます (メモリを節約します)。唯一の欠点は、行列に対処するために関数、マクロ、または厄介な表記法を使用する必要があることです。

2 番目のオプションを選択すると、任意の C99 コンパイラで次のような構造体を使用でき、ここでもメモリの単一ブロック (サイズ numints*sizeof(int)+sizeof(int)) を割り当てるだけで済みます。

struct matrix {
    int rows;
    int data[0];
}
于 2008-09-19T21:16:57.047 に答える
0

ここで見逃している概念は、calloc ごとに free が必要だということです。その解放は、calloc から返されたポインタに適用する必要があります。

ここで割り当てたすべてのポインターをループを使用して解放する関数 (delete_matrix という名前) を作成することをお勧めします。

for(int i = 0;i < size_x;i++) { 行列[i] = calloc(size_y, sizeof(int)); }

次に、それが完了したら、これによって割り当てられたポインターを解放します。

行列 = calloc(size_x, sizeof(int*));

今やっている方法で、

free(*first_matrix); 無料 (first_matrix);

あなたがしたいことはしません。

于 2008-09-19T21:21:08.753 に答える
0

first_matrix の最初の行 (または列) のみを解放しました。次のように別の関数を記述します。

void free_matrix(int **matrix, int rows)
{
    int i;
    for(i=0; i<rows; i++)
    {
        free(matrix[i]);
    }
    free(matrix);
}

行数と列数を格納するために、行列を構造体にしたい場合があります。

于 2008-09-19T21:14:59.923 に答える
0

バスエラーを発生させようとするのではなく、解放されていないメモリを追跡するために valgrind を使用することをお勧めします。他の多くのものにも対応しています。

サム

于 2008-09-19T21:15:28.797 に答える