释放三维矩阵的记忆

时间:2015-10-11 22:19:31

标签: c pointers memory-management

我在使用C进行图像处理时遇到了释放分配的内存的问题。我正在从文件中加载我的jpeg图像,然后根据图像是否在图像中执行某些操作灰度或RGB。

关键是加载数据的向量将具有以下两种结构之一:

data { R, G, B, R, G, B, ... }
// OR
data { value, value, value }

这就是我定义结构的方式:

typedef struct {
    int width;
    int height;
    int bytes_per_pixel;    /* 3 COLOR o 1 ESCALA DEGRISES  */
    int color_space;  /* JCS_RGB; o JCS_GRAYSCALE */
    unsigned char *dat;     /* vector de datos de la imagen descomprimida*/
    unsigned char **im;  /* matriz de punteros para acceder a cada valor de la imagen */
    unsigned char *** imgRGB;   // [i][j][0] red, [i][j][1] green,[i][j][2] blue
} imagenJPG;

始终分配im字段,而imgRGB仅在生成的图像为RGB时分配。我用这段代码做到了:

extern void  generar_imagen(imagenJPG *oimagen, int h, int w, int bytesxPixel, unsigned char val)
{
    int i, j;
    oimagen->width = w;
    oimagen->height = h;
    oimagen->bytes_per_pixel = bytesxPixel;
    if (bytesxPixel == 1)
        oimagen->color_space = JCS_GRAYSCALE;
    else
        oimagen->color_space = JCS_RGB;

    /* asignar memoria a la imagen*/

    if ((oimagen->dat = (unsigned char *) malloc(w*h * bytesxPixel * sizeof(unsigned char))) == NULL)
    {
        fprintf(stderr, "Funcion generar_imagen: malloc error\n");
        exit(1);
    }
    /*crear punteros a los pixeles segun el numero de componentes:*/

    if ((oimagen->im = (unsigned char **) malloc(h * sizeof(unsigned char *))) == NULL)
    {
        fprintf(stderr, "Funcion generar_imagen: malloc error\n");
        exit(1);
    }

    for(i = 0; i < h; i++) 
        oimagen->im[i] = &oimagen->dat[i * w * bytesxPixel];

    /* inicializar los pixeles de la imagen*/
    memset(oimagen->dat, val, h * w);

    if (bytesxPixel == 3)
    {
        /* para imagenes RGB una matriz de 3 dimensiones*/

        if ((oimagen->imgRGB = malloc(h * sizeof(unsigned char **))) == NULL)            
        {
            fprintf(stderr, "Funcion generar_imagen: malloc error\n");
            exit(1);
        }   

        for (i = 0; i < h; i++)
        {
            if ((oimagen->imgRGB[i] = malloc (w * sizeof(unsigned char *))) == NULL)            
            {
                fprintf(stderr, "Funcion generar_imagen: malloc error\n");
                exit(1);
            }

            for (j = 0; j < w; j++) {
                if ((oimagen->imgRGB[i][j] = malloc(3 * sizeof(unsigned char ))) == NULL)
                {
                    fprintf(stderr, "Funcion generar_imagen: malloc error\n");
                    exit(1);
                }  

                oimagen->imgRGB[i][j] = &oimagen->dat[i*w*3+3*j];
            }
        }


        /*   inicializar los pixeles de la imagen*/
        memset(oimagen->dat, val, h*w*3);
    }

}

这样我可以以二维方式访问图像的每个像素以获得灰度,并将第三维用于RGB。当我尝试释放图像时出现问题。这就是我的尝试:(与许多其他组合之间)

void  liberar_imagen(imagenJPG iimagen)
{        
    free(iimagen.dat);
    free(iimagen.im);

    if (iimagen.bytes_per_pixel==3)
    {
        int i, j;
        for (i = 0; i < iimagen.height; i++) {
            for (j = 0; j < iimagen.width; j++) {
                free(iimagen.imgRGB[i][j]);
            }
            free(iimagen.imgRGB[i]);
        }
        free(iimagen.imgRGB);
    }
}

我总是以段错误或双重自由腐败结束。我可以使程序运行的唯一方法是使用此功能:

void  liberar_imagen(imagenJPG iimagen)
{

    free(iimagen.dat);
    free(iimagen.im);

    if (iimagen.bytes_per_pixel == 3)
    {            
        free(iimagen.imgRGB);
    }

}

但遗憾的是,这并没有释放所有记忆 - 我该怎么做?

编辑:嗯,这就是我现在的方式,它就像一个魅力。但是,这是正确的方法吗?:(注意我只评论了分配)。

 for (j=0;j<w;j++){

               /* if ((oimagen->imgRGB[i][j] =malloc (3* sizeof(unsigned char )))== NULL )
                {
                    fprintf(stderr, "Funcion generar_imagen: malloc error\n");
                    exit(1);
                }*/  

                oimagen->imgRGB[i][j] = &oimagen->dat[i*w*3+3*j];
            }

释放内存的功能:

void  liberar_imagen(imagenJPG iimagen)
{
    int i;
    free(iimagen.dat);
    free(iimagen.im);

    if (iimagen.bytes_per_pixel==3)
    {
        for (i=0;i<iimagen.height;i++)
        free(iimagen.imgRGB[i]);
    }

            free(iimagen.imgRGB);

}

1 个答案:

答案 0 :(得分:1)

问题在于:

        for (j = 0; j < w; j++) {
            // *** an array of 3 chars is allocated
            if ((oimagen->imgRGB[i][j] = malloc(3 * sizeof(unsigned char ))) == NULL)
            {
                fprintf(stderr, "Funcion generar_imagen: malloc error\n");
                exit(1);
            }  
            // *** the pointer to the 3-char array is overwritten with a pointer to dat
            oimagen->imgRGB[i][j] = &oimagen->dat[i*w*3+3*j];
        }

当内存malloc'ed被覆盖时,会导致内存泄漏。然后你尝试释放每个oimagen->imgRGB[i][j]的内存,这不在malloc的块的开头。这会导致未定义的行为,在您的情况下会显示在核心转储中。

这可以通过简单地不在此块中分配任何内存来修复,并且随后不会尝试free它。

所以上面的循环现在看起来像这样:

        for (j = 0; j < w; j++) {
            oimagen->imgRGB[i][j] = &oimagen->dat[i*w*3+3*j];
        }

你的清理功能如下:

void  liberar_imagen(imagenJPG iimagen)
{        
    free(iimagen.dat);
    free(iimagen.im);

    if (iimagen.bytes_per_pixel==3)
    {
        int i;
        for (i = 0; i < iimagen.height; i++) {
            free(iimagen.imgRGB[i]);
        }
        free(iimagen.imgRGB);
    }
}