質問

メモリリークを発生させずに int 行列を生成する際に、いくつかの問題が発生しています。read_matrix() を介して、指定された (グローバル) 行列を動的に任意のサイズにできるようにしたいと考えています。しかし、後でメモリを解放できるようにしたいと思います。したがって、私の main メソッドでは、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]);
}
役に立ちましたか?

解決

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

ご了承ください free( *first_matrix ) 無料のものだけ 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 );

他のヒント

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


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

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

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

「バスエラー」を発生させたい場合は、プロセスに属さないメモリをポイントする必要があります。それにしても、なぜそんなことをしたいのですか?

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

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

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

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

サム

行列の最初の行と行のリストは解放しているが、1 行目から n 行目までは解放していないため、メモリ リークが発生します。ループ内でフリーコールする必要があります。

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

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

struct matrix {
    int rows;
    int data[0];
}

ここで欠けている概念は、すべての calloc に free が存在する必要があるということです。そして、その free は calloc から返されるポインタに適用されなければなりません。

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

for(int i = 0; i <size_x; i ++){matrix [i] = calloc(size_y、sizeof(int));}

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

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

今あなたがやっているやり方では、

free(*first_matrix);free(first_matrix);

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top