4维c ++数组的动态内存分配,用于创建HDF5数据集

时间:2018-03-05 11:53:02

标签: c++ arrays dynamic-memory-allocation hdf5

我在QT中有一个程序,它创建一个HDF5数据集并将其保存在磁盘中。

起初我定义了这个数组:

int data[dataNumber][dataFilter][dataWidth][dataHeight];

其中dataNumber=400000,dataFilter=1,dataWidth=2,dataHeight=2在此循环中我在此数组中设置了相同的值(当然为了简单起见):

for (int i = 0; i < dataNumber; i++)
    for (int j = 0; j < dataFilter; j++)
        for (int k = 0; k < dataWidth; k++)
            for (int l = 0; l < dataHeight; l++)
                data[i][j][k][l]=2;

之后我使用这些命令创建HDF5数据集:

// Create a new file using the default property lists.
H5File file(FILE_NAME, H5F_ACC_TRUNC);

datadims[0] = dataNumber;
datadims[1] = dataFilter;
datadims[2] = dataWidth;
datadims[3] = dataHeight;

IntType datatype( PredType::NATIVE_INT );
datatype.setOrder( H5T_ORDER_LE );
DataSpace dataspace(4, datadims);

// Create the dataset.
DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(data, PredType::NATIVE_INT);

并且一切都很好。

但是当我设置dataWidth=4,dataHeight=4时,segmentation fault发生了,我认为堆栈的保留大小会导致此问题,我应该使用Dynamic memory allocation

所以我更改了data数组,如下所示:

int ****data ;
data = new int***[dataNumber];
for( int i = 0 ; i < dataNumber ; i++ )
{
    data[i] = new int**[dataFilter] ;
    for( int j = 0 ; j < dataFilter ; j++ )
    {
        data[i][j] = new int*[dataWidth] ;
        for( int k = 0 ; k < dataWidth ; k++ )
            data[i][j][k] = new int[ dataHeight ] ;
     }
}

但在使用之后:

DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(data, PredType::NATIVE_INT);

HDF5数据集有很多错误的数字,例如-1865382688和-1720619824,而不是真数= 2。

现在我不知道如何解决这个问题。我希望有人可以提供帮助。

2 个答案:

答案 0 :(得分:2)

这是预期的:你传递一个指针数组(指向指针的指针),其中HDF5需要一个多维数组。 (有关内存布局差异的ASCII图形,请参阅我的answer to this other question。)如果您希望能够将内存传递给HDF5,则必须在一个块中分配内存。

在C ++中,您需要像Marko Popovic建议的那样:

int* data = new int[dataNumber*dataFilter*dataWidth*dataHeight];

自己做指数计算。我在此不再重复。

当然,您可以将索引计算封装在某种宏或模板中,但不管怎样,它都是PITA,可以在C ++中使用4D数组。

但是,如果您可以选择在C中编写此代码,那么有一个更好的选择:使用真正的4D数组。

int (*data)[dataFilter][dataWidth][dataHeight];
data = malloc(dataNumber*sizeof(*data));

在这里,data是指向4D阵列的3D拍击的指针,您可以分配dataNumber这样的拍击以获得4D阵列。有了这个,您可以像以前一样简单地索引4D数组:

data[i][j][k][l];

C将为您进行指数计算。

假设在编译时不知道您的数组大小,这种方法在C ++中是不可能的,因为C ++要求所有数组长度都是编译时常量。 C没有这个限制,允许自C99以来的动态数组大小。

答案 1 :(得分:1)

我建议分配一个连续的内存块,如下所示:

int *data = new int[dataNumber * dataFilter * dataWidth * dataHeight];

这意味着您需要调用一次new运算符,而不是多次调用它。只需拨打一个电话,这也可以轻松清理所有这些内存:

delete []data;

而不是再次调用删除数千次。之后,您可以使用以下内容索引到数组中:

data[((i*dataFilter + j)*dataWidth + k)*dataHeight + l];