在 C 中为 3D 数组分配连续内存
Allocating contiguous memory for a 3D array in C
我需要为 3D 数组分配连续的 space。 (编辑:)我想我应该首先明确这一点,但在实际的生产代码中,直到 运行 时间我才会知道数组的维度。为了简单起见,我在下面的玩具代码中将它们作为常量提供。我知道坚持连续 space 的潜在问题,但我只需要拥有它。我已经看到如何为 2D 阵列执行此操作,但显然我不明白如何将模式扩展到 3D。当我调用释放内存的函数 free_3d_arr
时,出现错误:
lowest lvl
mid lvl
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated
如果有人能告诉我修复方法是什么,我将不胜感激。代码在这里:
#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);
}
既然你用的是C,我建议你使用真正的多维数组:
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.
你可以这样做:
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);
}
我用过,效果很好。
我需要为 3D 数组分配连续的 space。 (编辑:)我想我应该首先明确这一点,但在实际的生产代码中,直到 运行 时间我才会知道数组的维度。为了简单起见,我在下面的玩具代码中将它们作为常量提供。我知道坚持连续 space 的潜在问题,但我只需要拥有它。我已经看到如何为 2D 阵列执行此操作,但显然我不明白如何将模式扩展到 3D。当我调用释放内存的函数 free_3d_arr
时,出现错误:
lowest lvl
mid lvl
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated
如果有人能告诉我修复方法是什么,我将不胜感激。代码在这里:
#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);
}
既然你用的是C,我建议你使用真正的多维数组:
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.
你可以这样做:
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);
}
我用过,效果很好。