使用结构的二维内存分配

2D memory allocation using structure

// 我必须创建一个新的 imgr_t,其中包含初始大小的行、列及其保留对应项(行和 reserved_rows 将相同,列和 reserved_cols 相同)。如果分配成功(即内存分配成功),returns 一个指向新分配的 imgr_t 的指针,如果不成功,returns 一个空指针。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

/* Structure type that encapsulates image: 2D array.
 * the rows represent the indices of the main array,
 * the cols represent the indices of the arrays pointed to by the pointers 
 * in the elements of the main array.
*/

typedef struct { 
    uint8_t** pixels;
    unsigned int rows;
    unsigned int cols;
    unsigned int reserved_rows;
    unsigned int reserved_cols;
} imgr_t;

/***** I am thinking something is wrong here but I cannot figure out what *****/

imgr_t* imgr_create(unsigned int rows, unsigned int cols){

    imgr_t* arr;
    arr->rows = rows;
    arr->cols = cols;
    arr->reserved_rows = rows;
    arr->reserved_cols = cols;
    arr = malloc(rows*sizeof(imgr_t));
    for(int i = 0; i<arr->rows; i++){
        arr->pixels[i] = malloc(cols*sizeof(imgr_t));
    }return arr;
}

void imgr_destroy(imgr_t* im){
    if(im != NULL){
        free(im->pixels);
        free(im);
    }
}

// helper function that prints the content of the img
void print_img(imgr_t* im) {
    if (im == NULL) {
        printf("Invalid img (null).\n");
        return;
    }

    printf("Printing img of row length %d and col length %d:\n", im->rows, im->cols);
    for (unsigned int i=0; i<im->rows; i++) {
        for (unsigned int j=0; j<im->cols; j++) {
            printf("%d ", im->pixels[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int main(){

  imgr_t* test_im;
  printf("Creating test_im by calling 'img_create(10, 10)'\n");
  test_im = imgr_create(10, 10);
  printf("test_im created successfully.\n\n");

    
  return 0;
}

/*
    Output what I am getting : Creating test_im by calling 'img_create(10, 10)'
             signal: segmentation fault (core dumped)
*/
imgr_t* imgr_create(unsigned int rows, unsigned int cols){

    imgr_t* arr;
    arr->rows = rows;
    arr->cols = cols;
    arr->reserved_rows = rows;
    arr->reserved_cols = cols;
    arr = malloc(rows*sizeof(imgr_t));
    for(int i = 0; i<arr->rows; i++){
        arr->pixels[i] = malloc(cols*sizeof(imgr_t));
    }return arr;
}

此处在初始化之前使用 arr。你的初始化似乎是错误的,因为你只需要分配 1 imgr_t 元素。像素初始化对我来说也是错误的:类型不正确,你需要使用类型uint8_t。您还需要分配一些 space 来存储您的像素:

imgr_t* imgr_create(unsigned int rows, unsigned int cols){

  imgr_t* arr = malloc(sizeof(imgr_t));
  arr->rows = rows;
  arr->cols = cols;
  arr->reserved_rows = rows;
  arr->reserved_cols = cols;
  arr->pixels = malloc(rows * sizeof(uint8_t*));

  for(int i = 0; i<arr->rows; i++){
    arr->pixels[i] = malloc(cols*sizeof(uint8_t));
  }

  return arr;
}

规则是 free 的调用次数与 malloc 的调用次数相同。 uint8_t** pixels; 不是指向二维数组的指针,而是指向数组指针的指针,因此您需要两次分配(在 free 时也是如此)。

这里你需要:

  • imgr_t 结构
  • 的 1 个分配
  • 1 行指针数组分配
  • 每行 1 次分配 (*)

代码可以是:

imgr_t* imgr_create(unsigned int rows, unsigned int cols) {

    imgr_t* arr = malloc(sizeof *arr);
    if (NULL == arr) return arr;       // do not forget to test allocation!
    arr->rows = rows;
    arr->cols = cols;
    arr->reserved_rows = rows;
    arr->reserved_cols = cols;
    arr->pixels = malloc(rows * sizeof(*arr->pixels));  // allocate rows
    if (NULL == arr->pixels) {         // another allocation to test
        free(arr);
        return NULL;
    }
    for (unsigned int i = 0; i < arr->rows; i++) {
        arr->pixels[i] = malloc(cols * sizeof(uint8_t));
        if (NULL == arr->pixels[i]) { // free what was allocated so far
            for (int j = 0; j < i; j++) {
                free(arr->pixels[i]);
            }
            free(arr->pixels)
            free(arr);
            return NULL;

        }
    }return arr;
}

void imgr_destroy(imgr_t* im) {
    if (im != NULL) {
        // one free per malloc...
        for (unsigned int i = 0; i < im->rows; i++) {
            free(im->pixels[i]);
        }
        free(im->pixels);
        free(im);
    }
}

注意:我无法理解 reserved 的意思,所以我忽略它...


(*) 事实上,可以一次分配整个数组,然后将指向行的指针指向全局数组中每一行的开头,但这是一种高级方法...