C++中的巨大2D数组

Huge 2D arrays in C++

本文关键字:2D 数组 巨大 C++      更新时间:2023-10-16

我正在编写一些进行图像处理的代码,它从原始图像文件中每隔16位读取一次,并将每个块存储到一个数组中。该阵列需要1392列和1024行。我正在用fread:从原始文件中读取数据块

    fread(&q1[0][0], sizeof(uint16_t), NUM_COLS*NUM_ROWS*sizeof(uint16_t), fp);

它似乎一直工作到q1[0][280],在那里它突然停止(超过280的值为0)。

我之前直接声明过数组:

uint16_t q1[NUM_COLS][NUM_ROWS];

但我认为它需要动态分配来存储280多个值,所以我把它重写为

    uint16_t** arr;
    arr= (uint16_t**) malloc(NUM_ROWS * sizeof(uint16_t *));
if (arr == NULL) {
    fprintf(stderr, "out of memoryn");
}
for(int i=0; i<NUM_ROWS; i++) {
    arr[i]= (uint16_t*) malloc(NUM_COLS * sizeof(uint16_t));
    if(arr[i] == NULL) {
        fprintf(stderr, "out of memoryn");
    }
}

不幸的是,这仍然停留在指数280。关于它为什么停止(或者是否有更好的方法),有什么想法吗?

首先,最好不要认为这样的数组太大。很可能您的平台确实支持几兆字节的全局数组。真的,你说的根本不是一个很大的物体。

其次,当数组中的行大小发生变化时,指针数组最有用。对于图形应用程序来说,这将降低空间局部性并损害性能。此外,您将调用mallocfree的次数比必要的次数多数千次,这些次数也可能相加。

一次读取NUM_COLS*NUM_ROWS*sizeof(uint16_t)字节的问题是图像在存储器中不再连续;它被划分为每一行的一个单独的内存块。尝试对每个malloc ed块执行单独的I/O操作……尽管我的建议是重新合并该块,如果它的大小真的是恒定的,则使其成为全局块。

您的二维数组是一个数组数组。

q1[0]是第一个子阵列的地址,q1[0][0]是第一子阵列中的第一个元素。然而,第二子阵列q1[1][0]是对malloc的不同调用的结果。因此,它不在第一个子阵列之后的连续存储器中。

您的读取调用填充了第一行,然后应该会导致分段错误,因为内存不是您期望的那样。

您必须分步骤读取数据,每个子数组一个。

您正在将NUM_COLS*NUM_ROWS整数读取到一个位置(&q1[0][0]),该位置不是已分配的NUM_COLS*NUM_ROWS整数块的开头。

你应该做的是:

for (int i = 0; i < NUM_ROS; ++i) {
    fread (q[i], sizeof(uint16_t), NUM_COLS, fp);
}

原因是,根据您的分配方式,每个"行"都是已分配的NUM_COLS整数块的开头。

此外,fread的第三个参数不是项的数量,而是项的大小。

如果这是用于读取的实际代码

fread(&q1[0][0], sizeof(uint16_t), NUM_COLS*NUM_ROWS*sizeof(uint16_t), fp);

您试图读取超出数组范围的内容。第二个参数是每个元素的大小,第三个参数是元素的数量。不能在两者中都有sizeof

您是否检查了fread的返回值,即实际读取的元素数?如果大于数组,则所有赌注都将取消!

当您以后改为分别分配每一行时,您还必须分别读取每一行,因为整个矩阵不再在连续内存中。

如果要使数组动态化,您可能需要考虑:

  • 使用Boost::multi_array

  • 分配一维数组:

    arr= (uint16_t *) malloc(NUM_ROWS*NUM_COLS*sizeof(uint16_t));
    

    并在列CCD_ 12和行CCD_

    arr[col*NUM_ROWS+row]
    

    这使用起来并不方便,但实现起来很简单。