堆栈内存使用连续动态分配的阵列与静态

时间:2016-03-21 21:58:17

标签: c multidimensional-array stack

我正在处理可变大小的3D和4D阵列,它们必须是连续的(有时common'方式更容易调用*(&x[0][0][0] + k)。 '因为数组的大小可变,我需要动态分配。我发现这个代码,在另一个答案(Dynamic memory allocation for 3D array)中做到这一点,它工作正常,但我不知道堆栈的内存使用量。

x[][][]

问题是:

  • double ***arr3dAlloc(const int ind1, const int ind2, const int ind3) { int i; int j; double ***array = (double***)malloc((ind1 * sizeof(double*)) + (ind1 * ind2 * sizeof(double**)) + (ind1 * ind2 * ind3 * sizeof(double))); for (i = 0; i < ind1; ++i) { array[i] = (double**)(array + ind1) + i * ind2; for (j = 0; j < ind2; ++j) { array[i][j] = (double*)(array + ind1 + ind1 * ind2) + i * ind2 * ind3 + j * ind3; } } return array; } double ***arr1 = arr3dAlloc(N1,N2,N3);之间有什么区别

  • 鉴于double arr2[N1][N2][N3];使用了堆栈的arr2内存,N1*N2*N3*sizeof(double)使用了多少内存?只有arr1

  • 一般来说,有没有一种方法来衡量任何变量的堆栈内存的使用?

3 个答案:

答案 0 :(得分:1)

指针具有指针的大小,具有相应的机器体系结构 (现在经常是longlong long)。该大小与所引用的内存类型无关。 (“**”只是指另一个指针。)

数组类型[N] 始终分配 sizeof(type)* N 字节的内存。 sizeof()包括类型填充到正确的对齐边界。 因此,使用malloc(sizof(type)*N)将为 type N 元素数组分配足够的内存,从而提供指向已分配内存块的指针。您也可以使用calloc()将内存初始化为零。

由于分配的内存不依赖于多维数组的组织,因此这种方法适用于任意数量的维度&gt; = 1.

解决您的问题:

  • double ***arr1 = …只是将指针存储到某个内存区域, 而arr2[N1][N2][N3]正在为N1*N2*N3双打分配填充空间。
  • arr1使用sizeof(void *)个字节, 而arr2正在使用N1*N2*n3*sizeof(double)字节。
  • sizeof(var)总是给出变量的大小, 这是在数据/ bss段还是在堆栈上。

答案 1 :(得分:1)

您的代码分配一个3D数组和指向double指针数组的指针数组,以通过双重间接访问其元素。这种方法存在一些问题:

  • 您的代码未在double边界上对齐double数组。如果指针的大小为4个字节且数组的大小为3x4x5,则double数组将不对齐,这可能会在某些系统上导致未定义的行为。

  • 您的尺寸计算中使用的类型是近似值。

  • 在计算非常大的矩阵的大小时,类型int可能会溢出。

这是一个更正版本(假设所有指针类型具有相同的大小):

double ***arr3dAlloc(int ind1, int ind2, int ind3) {
    size_t level1_size = sizeof(double**) * ind1;
    size_t level2_size = sizeof(double*) * ind1 * ind2;
    size_t padding = (sizeof(double) - (level1_size + level2_size) % sizeof(double))
                      % sizeof(double);
    size_t level3_size = sizeof(double) * ind1 * ind2 * ind3;
    int i, j;
    double ***array = calloc(1, level1_size + level2_size + padding + level3_size);
    double *array3d = (double*)((unsigned char*)array + level1_size + level2_size + padding);
    for (i = 0; i < ind1; ++i) {
        array[i] = (double**)(array + ind1) + i * ind2;
        for (j = 0; j < ind2; ++j) {
            array[i][j] = array3d;
            array3d += ind3;
        }
    }
    return array;
}

请注意,使用C99,您可以分配可直接在主计算代码中使用的真实3D数组:

/* array3d is a pointer to an allocated 3D array: */
double (*array3d)[ind2][ind3] = calloc(sizeof(*array3d), ind1);

/* array3d can be used like a statically defined array: */
for (int i = 0; i < ind1; i++) {
    for (int j = 0; j < ind2; j++) {
        for (int k = 0; k < ind3; k++) {
            array3d[i][j][k] = i + j + k;
        }
    }
}

答案 2 :(得分:0)

这里有几个问题需要解决。

第一个是全局变量,堆和堆栈之间的区别。这些都是RAM的所有部分。 malloc()分配一部分堆并返回一个指针。这在互联网上的许多其他地方都有讨论。

另一个问题是编译时与运行时分配。对于编译时分配,必须事先知道数组的大小。您的示例使用运行时分配(malloc()),因为数组的大小作为变量传递给函数。在编译时不知道它的大小,就无法在堆栈或全局变量中分配数组。