0

連続したメモリブロックを作成し、それを3D配列に割り当てる関数を作成しようとしています。このコードは、メモリを使用できるという点で機能します。この関数で作成されたオブジェクトに格納されているデータを使用すると、結果は正しく表示されます。ただし、この関数で割り当てたメモリを解放しようとすると、すぐにglibcエラーが発生します。関数は次のとおりです。

void *** matrix3d(int size, int rows, int cols, int depth) {
    void ***result;

    int col_size = depth * size;
    int row_size = (sizeof(void *) + col_size) * cols;
    int data_size = (rows * cols * depth + 1) * size;
    int pointer_size = rows * sizeof(void **) + cols * sizeof(void *);
    int i, j;
    char *pdata, *pdata2;

    if((result = (void ***) malloc(pointer_size + data_size)) == NULL)
            nerror("ERROR: Memory error.\nNot enough memory available.\n", 1);

    pdata = (char *) result + rows * sizeof(void **);

    if((long) pdata % (col_size + sizeof(void *)))
            pdata += col_size + sizeof(void *) - (long) pdata % (col_size + sizeof(void *));

    for(i = 0; i < rows; i++) {
            result[i] = pdata;

            pdata2 = pdata + cols * sizeof(void *);

            for(j = 0; j < cols; j++) {
                    result[i][j] = pdata2;
                    pdata2 += col_size;
            }

            pdata += row_size;
    }

    return result;
}

これは次のように呼び出されます。

double ***positions = (double ***) matrix3d(sizeof(double), numResidues, numChains, numTimesteps);

for(i = 0; i < numResidues; i++)
    for(j = 0; j < numChains; j++)
        for(k = 0; k < numTimesteps; k++)
             positions[i][j][k] = 3.2;

free(positions);

私は何を間違えましたか?お手伝いありがとう。

4

4 に答える 4

3

私は何を間違えましたか?

あなたのコードは理解するのが難しい (あなたはpdataたくさん遊んでいる) が、99% 割り当てられたスペースを超えて書き込んでおり、glibc によって残された簿記を台無しにしている.

書き込んだデータは問題なく使えます。唯一の問題は、無料で使用しようとするときです。

それglibcは、あなたがそれを呼び出したときにあなたがめちゃくちゃになるのを見る機会しか得られないからです.

于 2012-08-15T06:35:35.997 に答える
1

親愛なるサリーおばさん、失礼します。

int data_size = (rows * cols * depth + 1) * size;

これは次のようになります。

int data_size = (rows * cols * (depth + 1)) * size;

下のコードを実行するvalgrindと、すぐにエラーが特定されました。

于 2012-08-15T06:53:06.380 に答える
0

このようなものは物事を間違えるための素晴らしい候補です

pdata = (char *) result + rows * sizeof(void **);

コンパイラが自動的に行うアドレス計算を回避する理由はまったくありません。

于 2012-08-15T07:00:28.940 に答える
0

あなたがやっていることは、1 つの割り当てを 1 回行い、それをトリプル ポインターにキャストすることです。つまり、多くのオフセットを処理する必要があります。

おそらく、より多くの割り当てを行う方がよいでしょう:

char ***result = malloc(sizeof(char **) * rows);

for(i = 0; i < rows; i++) {
    result[i] = malloc(sizeof(char *) * cols);

    for(j = 0; j < cols; j++) {
        result[i][j] = malloc(sizeof(char) * size);

        /* Copy data to `result[i][j]` */
    }
}

解放するときは、すべての割り当てを解放する必要があります。

for(i = 0; i < rows; i++) {
    for(j = 0; j < cols; j++) {
        free(result[i][j]);
    }

    free(result[i]);
}

free(result);
于 2012-08-15T06:44:09.147 に答える