【问题标题】:Attempting to dynamically allocate a multidimensional array in C results in a crash尝试在 C 中动态分配多维数组会导致崩溃
【发布时间】:2013-02-13 11:04:28
【问题描述】:

出于多种原因,我想在连续的内存块中分配多维数组。我可以通过手动分配它们来做到这一点,例如:

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() 为 36 个指针分配 144 字节数组; 在 003E5728 处将指针数组分配到级别 1;

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

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

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

在 003E29E8 处分配连续数组;

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

【问题讨论】:

  • “我想在连续的内存块中分配多维数组” AFAIK,你不能决定,这取决于操作系统。
  • 为什么要修改dimension数组?
  • This answers the question 虽然没有解释这篇文章的具体问题。
  • 您的顶级和中间指针数组设置不正确。它们指向指针数组,而不是包含您的数据的东西。将它们分开something*sizeof(yourdata) 显然是一个错误。

标签: c arrays multidimensional-array dynamic-allocation contiguous


【解决方案1】:

a ⨉ b ⨉ c ⨉ d 数组 int 所需要的是:

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

【讨论】:

  • 我认为你是对的。但是,当您要将 Michał Gawlas 的多维数组设计传递给调用位置以外的函数时,它很容易使用。如果您只是分配一个连续的内存,则只能通过其他函数中的内存计算来完成访问。按照约定,在这个实现中,您可以简单地使用某种 ptr[i][j][k] 样式来访问任何地方的元素。
  • @flOyd:C 支持可变长度数组。您可以传递指针并在其他函数中访问它,方法是像这样传递参数:void /* or other type*/ foo(size_t b, size_t c, size_t d, int (*p)[b][c][d], /* other parameters */)。根本不需要这种关于多级指针的废话。
  • 感谢您指出这一点 - 我避免这样做是因为我记得我以前尝试这样做时它不起作用。
【解决方案2】:

我觉得有问题ptr[i]=ptr[i-1]+(*(dimension+1)*size);这种指针操作用法没有意义。我修改了如下代码,通过了四维数组的测试。

//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;
  }
}

【讨论】:

  • 谢谢。这确实是这里的问题:我忘记了 p+x(其中 p 是指针,x 是整数)等于 p[x] 而不是 p 之后的第 x 个字节。
猜你喜欢
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
  • 2015-02-15
  • 2019-08-11
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
相关资源
最近更新 更多