Search code examples
cpointersstructmallocfree

C usage of malloc on struct


I'm trying to use malloc on a struct called image. The function is:

void image_init(struct image* img, int w, int h) {
    img = malloc(sizeof(struct image));
    (*img).w = w;
    (*img).h = h;
}

And the function to free the image again is:

void image_destroy(struct image* img) {
    free(img);
}

But whenever I try to free the malloc-ed data I'm getting the error that the adress I'm trying to free was not malloc-ed before.

The struct of image is:

struct image {
    int w,h;
    int* data;
}

I call the functions with:

struct image img;
image_init(&img,100,100);
image_destroy(&img);

Solution

  • First here

    void image_init(struct image* img, int w, int h) {
        img = malloc(sizeof(struct image));
        (*img).w = w;
        (*img).h = h;
    }
    

    img is a copy of the original pointer passed to it, hence the code on first line inside function has no effect, since it makes the copy point somewhere - not the original object.

    This:

    struct image img;
    image_init(&img,100,100);
    image_destroy(&img);
    

    doesn't make sense either (assuming you expected img to point somewhere after call to init). img isn't a pointer, how you expect it to point somewhere?


    One way you could solve this could be

    struct image *img = image_init(100,100);
    

    where

    struct image* image_init(int w, int h) {
        img = malloc(sizeof(struct image));
        (*img).data = NULL;
        (*img).w = w;
        (*img).h = h;
        return img;
    }
    

    Don't forget to call free on the pointer returned by above function - you will need to free data pointer separately too, in case you allocate it too.


    NOTE: My best guess (if you also can't change prototype) is you want something like this:

    void image_init(struct image* img, int w, int h) {
        img->data = malloc(sizeof(int) * w * h);
        img->w = w;
        img->h = h;
    }
    

    destroy:

    void image_destroy(struct image* img) {
        free(img->data);
        free(img);
    }
    

    In main

    struct image* img = malloc(sizeof(struct image));
    image_init(img, 100, 100);
    image_destroy(img);
    

    PS. Or if you want the usage of those functions remain as you had in main go with the answer of Johnny Mopp.