#c #pointers #malloc #valgrind #free
#c #указатели #маллок #валгринд #Бесплатно
Вопрос:
Я новичок в программировании, и я писал программу для восстановления файлов JPEG, присутствующих в «card.raw», путем сравнения 4 непрерывных байтов. Если они разграничили JPEG, программе пришлось скопировать блок из 512 байт в новый файл, сохраненный xxx.jpg (000.jpg , 001.jpg , и т.д.). Если после копирования блока было найдено начало нового JPEG, текущий файл будет закрыт, а следующий файл будет открыт для копирования следующего JPG. Иначе следующий блок будет скопирован в тот же файл.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int counter = 0;
if(argc != 2)
{
printf("Usage: ./recover imagen");
return 1;
}
typedef uint8_t BYTE;
FILE *recover = fopen(argv[1], "r");
if(recover == NULL)
{
printf("ERRNO 1 IS %sn", strerror(errno));
exit(EXIT_FAILURE);
}
fseek(recover, 0L, SEEK_END);
unsigned long size = ftell(recover);
fseek(recover, 0L, SEEK_SET);
BYTE *CHUNK = (BYTE*)malloc(size * sizeof(BYTE));
fread(CHUNK, sizeof(BYTE), size, recover); //Break recover into bytes
int j = 0;
char file[8] = "xxx.jpg";
FILE *f = NULL;
int s = 0;
while(j < size)
{
if(CHUNK[j] == 0xff amp;amp; CHUNK[j 1] == 0xd8 amp;amp; CHUNK[j 2] == 0xff) //Check if byte is JPEG format 1st byte
{
if(s == 0)
{
if(f != NULL)
{
f = NULL;
}
sprintf(file ,"d.jpg",counter); //Create custom file of format xxx.jpg
f = fopen(file,"w");
if(f == NULL)
{
printf("ERRNO 2 is %sn", strerror(errno));
exit(EXIT_FAILURE);
}
fwrite(amp;CHUNK[j], 512, sizeof(BYTE), f); //Copy 512 bytes from start of JPEG file as 512 bytes form one 'block`
j = 512; //Increment to check initial bytes of next 'block'
s ;
}
else
{
fclose(f);
counter ;
s = 0;
}
}
else if(s > 0) //Else continue searching
{
fwrite(amp;CHUNK[j], 512, sizeof(BYTE), f);
j = 512;
}
else j = 512;
}
fclose(f);
fclose(recover);
free(amp;CHUNK);
return 0;
}
Программа работала отлично, за исключением того факта Valgrind
, что она выдает мне следующий отчет:
==1560== Memcheck, a memory error detector
==1560== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1560== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1560== Command: ./recover card.raw
==1560==
==1560== Invalid free() / delete / delete[] / realloc()
==1560== at 0x4C32D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1560== by 0x400BF4: main (recover.c:69)
==1560== Address 0x1fff000510 is on thread 1's stack
==1560== in frame #1, created by main (recover.c:9)
==1560==
==1560==
==1560== HEAP SUMMARY:
==1560== in use at exit: 3,744,768 bytes in 1 blocks
==1560== total heap usage: 103 allocs, 103 frees, 3,981,816 bytes allocated
==1560==
==1560== 3,744,768 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1560== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1560== by 0x4009FA: main (recover.c:26)
==1560==
==1560== LEAK SUMMARY:
==1560== definitely lost: 3,744,768 bytes in 1 blocks
==1560== indirectly lost: 0 bytes in 0 blocks
==1560== possibly lost: 0 bytes in 0 blocks
==1560== still reachable: 0 bytes in 0 blocks
==1560== suppressed: 0 bytes in 0 blocks
==1560==
==1560== For counts of detected and suppressed errors, rerun with: -v
==1560== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Valgrind
кажется, говорят, что проблема связана с выделением памяти в line 26
:
BYTE *CHUNK = (BYTE*)malloc(size * sizeof(BYTE));
Но я освободил выделенную память с free(amp;CHUNK);
помощью в конце. Я хотел бы знать, почему Valgrind
появились такие сообщения 3,744,768 bytes in 1 blocks
definitely lost
.
Комментарии:
1. Не имеет отношения к вашей проблеме: есть ли какая-то конкретная причина, по которой вы читаете весь файл в памяти? Поскольку вы обрабатываете его поблочно, вам нужно только читать / обрабатывать 512 байт за раз, в этом нет
malloc
необходимости
Ответ №1:
free(amp;CHUNK)
запрашивает free
пространство для переменной CHUNK
, то есть (например, 4 или 8) байт, которые занимает сам указатель; помимо того, что вы не освобождаете память, о которой вы думаете, это неопределенное поведение, поскольку вы можете free
использовать только память, которая была выделена malloc
and friends , и я удивлен, что вы не получаете сбой из-за некоторой проверки работоспособности внутри распределителя.
Что вам на самом деле нужно сделать, так это освободить указанную память CHUNK
, так что вы должны это сделать free(CHUNK)
.
Комментарии:
1. Дополнительным доказательством является то, что valgrind сообщает
Invalid free()
в строке 69 и отмечаетAddress 0x1fff000510 is on thread 1's stack
.2. @FredLarson
thread 1's stack
Ссылается ли здесь на стек, к которому обращается программаmain
?3. @MelPradeep да, это первый (и единственный) поток вашего приложения.