0

Hello my task is to copy full structure into a new one, and allocate structure memory. I want to copy one structure into another and also I want to copy the memory of it. So if I "free" the first structure, then I will have this information in the memory located.

 struct bmp_image* flip_vertically(const struct bmp_image* image) {
    struct bmp_image* bmp = NULL;
    bmp = (struct bmp_image*)realloc(bmp, sizeof(struct bmp_image)); 
    memcpy(bmp, image, sizeof(struct bmp_image));

   return bmp;
}

What can be the problem?

For example:

If I know that the

image->data[5].blue is 255 and I want to copy it but I need also to save that information into the memory

Main task is to flip the bmp picture. Everything is working perfect for me, but if I put this source code for test that writes that:

Running suite(s): flip_horizontally()

stderr

double free or corruption (!prev)

that means the test is somewhere free-ing the old structure so I don't have this information in the new one

struct bmp_header{
    uint16_t type;              // "BM" (0x42, 0x4D)
    uint32_t size;              // file size
    uint16_t reserved1;         // not used (0)
    uint16_t reserved2;         // not used (0)
    uint32_t offset;            // offset to image data (54B)
    uint32_t dib_size;          // DIB header size (40B)
    uint32_t width;             // width in pixels
    uint32_t height;            // height in pixels
    uint16_t planes;            // 1
    uint16_t bpp;               // bits per pixel (1/4/8/24)
    uint32_t compression;       // compression type (0/1/2) 0
    uint32_t image_size;        // size of picture in bytes, 0
    uint32_t x_ppm;             // X Pixels per meter (0)
    uint32_t y_ppm;             // X Pixels per meter (0)
    uint32_t num_colors;        // number of colors (0)
    uint32_t important_colors;  // important colors (0)
} __attribute__((__packed__));


/**
 * This structure describes a color consisting of relative intensities of
 * red, green, and blue.
 */
struct pixel {
    uint8_t blue;
    uint8_t green;
    uint8_t red;
    //uint8_t alpha;
} __attribute__((__packed__));


/**
 * Structure describes the BMP file format, which consists from two parts:
 * 1. the header (metadata)
 * 2. the data (pixels)
 */
struct bmp_image {
    struct bmp_header* header;
    struct pixel* data;         // nr. of pixels is `width` * `height`
};

Main.c

int main () {
struct bmp_image* image = NULL;
    FILE *stream = fopen("assets/saboteur.bmp", "r");
    image = read_bmp(stream);

    FILE *output_p1 = fopen("square2.bmp", "w");
    struct bmp_image* newimage1 = NULL;
    newimage1 = flip_vertically(image);
    free_bmp_image(image);
    write_bmp(output_p1, newimage1);

    free(newimage1);     
    fclose(output_p1);
    fclose(stream);
    return 0;
}

If I free the image (the old structure) it shows for me a lot of errors, and I can't write it to the file. That means for me that it wants to read from the old structure.

a2800276
  • 3,272
  • 22
  • 33
  • 3
    looks okay but why using `realloc` when `malloc` would work? and what is your problem? If `bmp_image` contains pointers to data and you want to duplicate that too, you have to do it manually. Allocating a new structure isn't enough as you just copied the pointers – Jean-François Fabre Apr 23 '20 at 22:25
  • What specific issues are you encountering? What makes you suspect there is a problem in that code? If you need further help please provide a [minimal verifiable example](https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-on-so-when-asking-a-question) and what errors you may have. Include input, expected result and actual result. – kaylum Apr 23 '20 at 22:26
  • [dont cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Apr 23 '20 at 22:27
  • As already stated - you need to provide a minimal verifiable example. For example, we don't know how `struct bmp_image` is defined which could be critical here. " i want to copy it but i need also to save that information into the memory" - that's what you want to do, but you still haven't told us what problem you have. Did you get a crash? Did you get incorrect results somewhere? etc. – kaylum Apr 23 '20 at 22:34
  • It would help if you could include a definition of `struct bmp_image`. Also, **show us the results you're getting and explain why they are different than the results you want.** – William Rosenbloom Apr 23 '20 at 22:34
  • 1
    If the `struct bmp_image` is defined as shown in your [other question](https://stackoverflow.com/questions/61375776/bmp-image-pixels-in-1d-array-structure-in-c-padding-issue) then the problem is as has been guessed by a few of us. `mempcy` does a "shallow" copy. It copies the pointer values in the struct and not what they point to. You need to allocate memory for each of the struct members and do a `memcpy` for each. – kaylum Apr 23 '20 at 22:41
  • i edited the problem check it out, probably it will helps to explain the main problem – juhandergod Apr 23 '20 at 22:43
  • *sigh* No it's not helpful. Can you please read the link on how to create a [minimal verifiable example](https://stackoverflow.com/help/minimal-reproducible-example) and [how to ask](https://stackoverflow.com/help/how-to-ask). We have even told you very specifically that we need to see the **`struct bmp_image` definition** – kaylum Apr 23 '20 at 22:45
  • Sorry for misunderstanding im new here, and i really stuck with that problem, i refreshed the infromation about the structure – juhandergod Apr 23 '20 at 22:50
  • @juhandergod You did only one-third of the job. You created a new `bmp_image`, but it still points to the same `bmp_header` and `pixel` data as the original one. You need to do (almost) the same thing two more times. – David Schwartz Apr 23 '20 at 22:54
  • struct bmp_image* bmp = (struct bmp_image*)malloc(sizeof(struct bmp_image)); memcpy(bmp, image, sizeof(struct bmp_image)); struct header* header = (struct header*)malloc(sizeof(struct header)); memcpy(header, image->header, sizeof(struct header)); struct data* data = (struct data*)malloc(sizeof(struct data)); memcpy(data, image->data, sizeof(struct data)); That would work? – juhandergod Apr 23 '20 at 22:58
  • Not quite. You did not assign the `header` and `data` back to `bmp->header` and `bmp->data`. In fact you don't need the first `memcpy` and you don't need temporary `header` and `data` pointers. Just `malloc` and `memcpy` directly into `bmp->header` and `bmp->data`. Finally the size of the `malloc` for `data` is wrong. You need to allocate enough memory for the number of pixels as determined by width*height. – kaylum Apr 23 '20 at 23:05
  • struct bmp_image* bmp = NULL; bmp = calloc(3*bmp->header->width*bmp->header->height, sizeof(struct bmp_image)); memcpy(bmp->header, image->header, sizeof(struct bmp_image)); memcpy(bmp->data, image->data, sizeof(struct bmp_image*)); what about that? :D sry for disturbing but i really stuck here for a lot of time, but really thanks for helping – juhandergod Apr 23 '20 at 23:13

1 Answers1

1

memcpy does a "shallow" copy and not a "deep" copy. A shallow copy will copy only the pointer values in the struct bmp_image and not the memory it points to. To do a deep copy, the individual fields need to be allocated and copied. Here is some illustrative code. Error checking has been left out for brevity but for final code all allocation results should be checked.

struct bmp_image* flip_vertically(const struct bmp_image* image) {
    bmp = malloc(sizeof(*bmp)); 

    bmp->header = malloc(sizeof(*(bmp->header)));
    *bmp->header = *(image->header);

    size_t pixel_data_size =
        sizeof(*(bmp->data)) * bmp->header->width * bmp->header->height;
    bmp->data = malloc(pixel_data_size);
    memcpy(bmp->data, image->data, pixel_data_size);

   return bmp;
}
kaylum
  • 13,833
  • 2
  • 22
  • 31