C ++中的巨大二维数组

时间:2011-06-20 20:52:56

标签: c++ c arrays

我正在研究一些执行图像处理的代码,它从原始图像文件中读取每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 memory\n");

}
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 memory\n");

    }
}

不幸的是,这仍然停留在索引280处。任何关于它为何停止的想法(或者是否有更好的方法)?

5 个答案:

答案 0 :(得分:5)

首先,最好不要假设这样的阵列太大了。您的平台很可能支持几兆字节的全局数组。真的,你根本不是在谈论一个非常大的对象。

其次,当行数在数组数组中变化时,指针数组最有用。对于图形应用程序,这将降低空间局部性并损害性能。此外,您还会拨打mallocfree数千次,这也可以加起来。

一次读取NUM_COLS*NUM_ROWS*sizeof(uint16_t)个字节的问题是图像在内存中不再连续;它被划分为每行的单独内存块。为每个malloc ed块尝试单独的I / O操作......虽然我的建议是重新组合该块,如果它的大小确实是常量,则将其设置为全局。

答案 1 :(得分:4)

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

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

你的阅读电话填满了第一行,然后应该导致分段错误,因为内存不是你期望的那样。

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

答案 2 :(得分:2)

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

你应该做的是:

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

原因在于,根据您分配的方式,每个'row'是NUM_COLS整数的已分配块的开头。

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

答案 3 :(得分:2)

如果这是您的实际阅读代码

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

你尝试读取的方式不仅仅适合数组。第二个参数是每个元素的大小,第三个参数是元素的数量。您不能同时拥有sizeof

您是否检查了fread的返回值,实际读取的元素数量是多少?如果它大于数组,则所有投注均已关闭!

当你稍后改为分别分配每一行时,你还必须分别读取每一行,因为整个矩阵不再是连续的内存。

答案 4 :(得分:0)

如果您使阵列动态化,您可能需要考虑:

  • 分配一维数组:

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

    并在col列和第row行访问它,如下所示:

    arr[col*NUM_ROWS+row]
    

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