0

由于多种原因,我想在连续的内存块中分配多维数组。试图在C中动态分配多维数组会导致崩溃

t.versions=(char***)malloc(sizeof(char**)*4); 
t.versions[0]=(char**)malloc(sizeof(char*)*t.size*4); 
t.versions[0][0]=(char*)calloc(t.size*t.size*4,sizeof(char)); 
for (i=1; i<t.size*4; ++i) 
    t.versions[0][i]=t.versions[0][i-1]+t.size; 
for (i=1; i<4; ++i) 
    t.versions[i]=t.versions[i-1]+t.size; 

除了其他优点,该解决方案简化释放所分配的内存:

void contiguous_array_free(void** ptr, int depth) 
{ 
    int *ptr_d; 
    ptr_d=(int*)*ptr; 
    if (depth>1) 
     contiguous_array_free((void**)ptr_d, depth-1); 
    free(ptr); 
} 
//(elsewhere in the code) 
contiguous_array_free((void**)(*tile).versions, 3); 

现在,我有一个小问题,分配我可以通过手动分配它们,例如,做到这一点这些数组 - 虽然上面发布的方法确实有效,但理想情况下,我希望有一个通用解决方案,允许我通过单个函数调用来分配这些数组。

但是,我试图实现该目标会导致程序在每次使用数组内容时崩溃。

//dimension points to a 1-dimensional array of integers 
//specifying the size in each array dimension 
void* contiguous_array_alloc(int* dimension, int depth, int size) 
{ 
    int i; 
    char** ptr; 
    if (depth==1) 
    { 
     ptr=(char**)malloc(*dimension*size); 
     return ptr; 
    } 
    ptr=(char**)malloc(*dimension*sizeof(char*)); 
    *(dimension+1)*=*dimension; 
    ptr[0]=(char*)contiguous_array_alloc(dimension+1, depth-1, size); 
    *(dimension+1)/=(*dimension); 
    for (i=1; i<*dimension; ++i) 
     ptr[i]=ptr[i-1]+(*(dimension+1)*size); 
    return (void*)ptr; 
} 

//(later in the code) (
int dimension[3]; 
dimension[0]=4; 
dimension[1]=t.size; 
dimension[2]=t.size; 
t.versions=(char***)contiguous_array_alloc(&dimension[0], 3, sizeof(char)); 

添加一些调试消息到代码似乎表明该元件被正确地分配:

清分[4] [9] [9]的大小1个元件的阵列; malloc()在4个指针的16字节数组中; 将指针数组分配到003E29E8级别2;

分配[36] [9]大小为1的元素的数组; malloc()在144个字节数组中,用于36个指针; 将指针数组分配到003E5728级别1;

分配大小为1的元素的数组;

324字节的数据数组在003E57C0; 指向003E57C0的数据; 将每个指针增加9; 返回分配的数组;

指向003E5728; 将每个指针增加9; 返回分配的数组;

在003E29E8处分配连续数组;

是什么导致了这种行为?我已经检查了几次代码,不知道我做错了什么。

+1

*“我想分配在连续的多维数组大块的内存“* AFAIK,你不能决定,这取决于操作系统。 – m0skit0 2013-02-27 15:12:04

+6

[Obligatory ...](http://c2.com/cgi/wiki?ThreeStarProgrammer) – Mysticial 2013-02-27 15:14:18

+0

为什么要修改'dimension'数组? – WhozCraig 2013-02-27 15:14:55

回答

1

我认为ptr[i]=ptr[i-1]+(*(dimension+1)*size);这样的指针操作用法没有任何意义。我修改了下面通过4维数组测试的代码。

//dimension points to a 1-dimensional array of integers 
//specifying the size in each array dimension 
void* contiguous_array_alloc(int* dimension, int depth, int size) { 
    int i; 
    if (depth==2) { 
    char ** ptr=(char **)malloc(*dimension * sizeof(void*)); 
    ptr[0]=(char *)malloc(*dimension * dimension[1] * size); 
    for (i=1; i<*dimension; ++i) { 
     ptr[i]=ptr[i-1]+(*(dimension+1) * size); 
    } 
    return (void*)ptr; 
    } else { 
    void ***ptr=(void***)malloc(*dimension * sizeof(void*)); 
    *(dimension+1)*=(*dimension); 
    ptr[0]=contiguous_array_alloc(dimension+1, depth-1, size); 
    *(dimension+1)/=(*dimension); 
    for (i=1; i<*dimension; ++i) { 
     ptr[i]=ptr[i-1]+(*(dimension+1)); 
    } 
    return (void*)ptr; 
    } 
} 
+0

谢谢。这确实是这里的问题:我忘记了p + x(其中p是一个指针,x是一个整数)等于p [x],而不是p之后的第x个字节。 – 2013-02-27 19:14:30

0

所有你需要用于一个bÇdint阵列是:

int (*p)[b][c][d] = calloc(a, sizeof *p); 
+0

我认为你是对的。但是,MichałGawlas的多维阵列设计很容易使用,当你想将它传递给你的功能以外的其他功能。如果您只是分配连续内存,则只能通过其他功能中的内存计算完成访问。按照契约,在这个实现中,你可以简单地使用某种类型的ptr [i] [j] [k]样式来访问任何地方的元素。 – fLOyd 2013-02-27 18:28:41

+1

@flOyd:C支持可变长度的数组。您可以传递指针并通过传递参数来访问其他函数:'void/*或其他类型*/foo(size_t b,size_t c,size_t d,int(* p)[b] [c] [d],/ *其他参数* /)'。根本不需要关于多级指针的这种废话。 – 2013-02-27 18:39:46

+0

它确实有效!它太酷了。感谢您的建议。 – fLOyd 2013-02-27 19:02:33