I’m working on some code that does image manipulation, and it reads every 16 bits from a raw image file and stores each block into an array. The array needs 1392 columns and 1024 rows. I’m reading in data blocks from the raw file with fread:
fread(&q1[0][0], sizeof(uint16_t), NUM_COLS*NUM_ROWS*sizeof(uint16_t), fp);
which seems to work up until q1[0][280], where it suddenly stops (values past 280 are 0).
I had previously declared arrays directly:
uint16_t q1[NUM_COLS][NUM_ROWS];
but I thought that it would need dynamic allocation to store more than 280 values, so I re-wrote it to be
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");
}
}
Unfortunately, this still stops at index 280. Any ideas as to why it’s stopping (or if there’s a better way of doing this)?
First, it’s better not to presume that such an array will be too big. Most likely your platform does support a global array of a couple megabytes. Really you’re not talking about a very big object at all.
Second, an array of pointers is most useful when the row size varies within the array of arrays. For a graphics application, this will degrade spatial locality and hurt performance. Also, you will call
mallocandfreethousands of times more than necessary, which can also add up.The problem with reading
NUM_COLS*NUM_ROWS*sizeof(uint16_t)bytes at once is that the image is no longer contiguous in memory; it’s divided into a separate block of memory for each row. Try a separate I/O operation for eachmalloced block… although my recommendation would be to reconsolidate that block instead, and if its size is really constant, make it a global.