我正在研究一些执行图像处理的代码,它从原始图像文件中读取每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处。任何关于它为何停止的想法(或者是否有更好的方法)?
答案 0 :(得分:5)
首先,最好不要假设这样的阵列太大了。您的平台很可能支持几兆字节的全局数组。真的,你根本不是在谈论一个非常大的对象。
其次,当行数在数组数组中变化时,指针数组最有用。对于图形应用程序,这将降低空间局部性并损害性能。此外,您还会拨打malloc
和free
数千次,这也可以加起来。
一次读取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]
这不方便使用,但实施起来很简单。