0

This my solution to recover problem. It works, but it produces "munmap_chunk(): invalid pointer" error:

enter image description here

And Valgrind outputs:

==5906== LEAK SUMMARY:

==5906== definitely lost: 0 bytes in 0 blocks

==5906== indirectly lost: 0 bytes in 0 blocks

==5906== possibly lost: 0 bytes in 0 blocks

==5906== still reachable: 135,532 bytes in 1,242 blocks

==5906== suppressed: 0 bytes in 0 blocks

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

typedef uint8_t BYTE;

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
    {
        printf("The image cannot be opened for reading\n");
        return 2;
    }

    int file_number = 0;
    const int bytes = 512;
    char *filename = NULL;
    FILE *img = NULL;

    BYTE *buffer = malloc(sizeof(BYTE) * 64);
    if (buffer == NULL)
    {
        fclose(file);
        fprintf(stderr, "Could not create a buffer.\n");
        return 3;
    }
    //BYTE buffer[512];

    while (fread(buffer, bytes, 1, file) > 0)
    {
        if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
        {
            if (file_number != 0)
            {
                fclose(img);
            }

            filename = malloc(sizeof(char) * 8);
            if (filename == NULL)
            {
                fclose(file);
                free(buffer);
                fprintf(stderr, "Could not create a filename.\n");
                return 4;
            }
            sprintf(filename, "%03i.jpg", file_number);

            img = fopen(filename, "w");
            if (img == NULL)
            {
                fclose(file);
                free(buffer);
                free(filename);
                fprintf(stderr, "Could not create an image.\n");
                return 6;
            }

            fwrite(buffer, bytes, 1, img);
            file_number++;
            //free(filename);
        }
        else
        {
            if (file_number != 0)
            {
                fwrite(buffer, bytes, 1, img);
            }
        }

        //free(buffer);
        //buffer = malloc(sizeof(BYTE) * 64);
    }


    free(filename);
    free(buffer);
    fclose(img);
    fclose(file);
    return 0;
}

If I use buffer as an array it would work fine without any errors. So I think the problem with the buffer pointer but I can't seem to figure it out.

1

The problem is in the following statement:

BYTE *buffer = malloc(sizeof(BYTE) * 64);

if you think about it, BYTE has a size of 64 bytes, because the size in bytes of uint_8 is 1 byte or 8 bits, therefore the allocated memory is insufficient. This causes strange behavior in the result. All you have to do is assign the correct memory with malloc:

BYTE *buffer = malloc(8 * 64);

Or better yet use an array so you don't have to use free ().

2
  • Thank you. This does solve it. I thought sizeof(BYTE) returns 8 not 1. But what about the valgrind's message "still reachable: 135,532 bytes in 1,242 blocks"? Dec 5 '19 at 8:23
  • There is a problem reserving memory for filename within the while loop. Each time that loop is executed, memory is stored in different blocks of memory, but only one is freed. The solution would be to get it out while loop
    – MARS
    Dec 5 '19 at 21:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .