2016-08-23 7 views
0

3D配列に連続したスペースを割り当てる必要があります。 (編集:)私は、最初の場所でこのクリアを作成しなければなりませんでしたが、実際の生産コードでは、実行時まで配列の寸法はわかりません。物事を単純にするために、以下の私のおもちゃのコードでそれらを定数として提供しました。私は連続した空間を主張する潜在的な問題を知っていますが、私はそれを持っていなければなりません。私は2D配列に対してこれを行う方法を見てきましたが、明らかにパターンを3Dに拡張する方法を理解していません。私はメモリ、free_3d_arrを解放する関数を呼び出すと、私はエラーを取得する:誰でも修正があるものを私に言うことができる場合Cの3D配列に連続したメモリを割り当てる

lowest lvl 
mid lvl 
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated 

はそれをお願い申し上げます。コードはここにある:あなたがCを使用しているので

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

int ***calloc_3d_arr(int sizes[3]){ 

    int ***a; 
    int i,j; 

    a = calloc(sizes[0],sizeof(int**)); 
    a[0] = calloc(sizes[0]*sizes[1],sizeof(int*)); 
    a[0][0] = calloc(sizes[0]*sizes[1]*sizes[2],sizeof(int)); 

    for (j=0; j<sizes[0]; j++) { 
     a[j] = (int**)(a[0][0]+sizes[1]*sizes[2]*j); 
     for (i=0; i<sizes[1]; i++) { 
     a[j][i] = (int*)(a[j]) + sizes[2]*i; 
     } 
    } 

    return a; 

} 



void free_3d_arr(int ***arr) { 

    printf("lowest lvl\n"); 
    free(arr[0][0]); 
    printf("mid lvl\n"); 
    free(arr[0]);   // <--- This is a problem line, apparently. 
    printf("highest lvl\n"); 
    free(arr); 

} 



int main() { 

    int ***a; 
    int sz[] = {5,4,3}; 
    int i,j,k; 

    a = calloc_3d_arr(sz); 

    // do stuff with a 

    free_3d_arr(a); 

} 
+1

'a [0] = ...'の後に 'a [j] = ...'がついているようです... –

+1

3次元配列はありません。あなたのコード!ポインタは配列ではありません! 3D配列が必要な場合は、1つを使用します。ああ、3スターのCプログラマであることは褒め言葉ではありません。 – Olaf

+1

これは、SOはクラウドソースデバッガではないことを示しています。 –

答えて

3

、私はあなたが本当の多次元配列を使用することを示唆している:

int (*a)[sz[1]][sz[2]] = calloc(sz[0], sizeof(*a)); 

これはあなたの3Dアレイの連続したストレージを割り当てます。 C99以降のサイズは動的であることに注意してください。あなたは、ポインタの配列と同じようにあなたは、まさにこの配列にアクセス:

for(int i = 0; i < sz[0]; i++) { 
    for(int j = 0; j < sz[1]; j++) { 
     for(int k = 0; k < sz[2]; k++) { 
      a[i][j][k] = 42; 
     } 
    } 
} 

はしかし、ボンネットの下には、ポインタの配列が存在しない、インデックスはポインタ演算と配列ポインタ崩壊の魔法によって行われます。単一calloc()がものを割り当てるために使用されたので、単一free()はそれを取り除くために足りる:

free(a); //that's it. 
+2

Nitpicking:これらの 'int'は' size_t'sでなければなりません。 – alk

+1

わずかな追加:C11はVLAをオプションにしました(主な疑いがあるのは、C99とC90互換の高価なツールを販売している組み込みコンパイラベンダーを有名にする大企業です)。現代のコンパイラがVLAをサポートするだろうと言った。 – Olaf

+0

@Bob__ありがとうございます:-)私は、 'calloc()'が 'malloc()'が使っていないsize引数のこの*面白い*分割を使うことを常に忘れています。しかし、私は今それを修正しました。 – cmaster

1

あなたはこのような何かを行うことができます。私はそれを使用すると、正常に動作します

int ***allocateLinearMemory(int x, int y, int z) 
{ 
    int *p = (int*) malloc(x * y * z * sizeof(int)); 
    int ***q = (int***) malloc(x * sizeof(int**)); 
    for (int i = 0; i < x; i++) 
    { 
     q[i] = (int**) malloc(y * sizeof(int*)); 
     for (int j = 0; j < y; j++) 
     { 
      int idx = x*j + x*y*i; 
      q[i][j] = &p[idx]; 
     } 
    } 
    return q; 
} 

void deallocateLinearMemory(int x, int ***q) 
{ 
    free(q[0][0]); 
    for(int i = 0; i < x; i++) 
    { 
     free(q[i]); 
    } 
    free(q);  
} 

を。

+0

申し訳ありません、コピー貼り付け、そのCを知っています。 –

関連する問題