gcc 4.4.4 c89no se puede liberar la memoria
Tengo la siguiente función pero no puedo liberar la memoria. El mensaje que recibo en Valgrind sospecha de la función getline. Sin embargo, estoy libre del puntero al final de la función. Entonces no puede ser eso.
Tengo una matriz global de punteros a char 'candidates_names'. Sin embargo, no he asignado ningún recuerdo para eso.
Muchas gracias por cualquier consejo,
El mensaje que recibo en valgrind es la siguiente.
HEAP SUMMARY:
==4021== in use at exit: 840 bytes in 7 blocks
==4021== total heap usage: 22 allocs, 15 frees, 1,332 bytes allocated
==4021==
==4021== Searching for pointers to 7 not-freed blocks
==4021== Checked 48,412 bytes
==4021==
==4021== 840 bytes in 7 blocks are still reachable in loss record 1 of 1
==4021== at 0x4005BDC: malloc (vg_replace_malloc.c:195)
==4021== by 0xAAE38D: getdelim (iogetdelim.c:68)
==4021== by 0xAAADD2: getline (getline.c:34)
==4021== by 0x804892B: load_candidates (candidate.c:61)
==4021== by 0x8048686: main (driver.c:24)
mi código fuente:
#define NUMBER_OF_CANDIDATES 7
static char *candidate_names[NAME_SIZE] = {0};
int load_candidates()
{
FILE *fp = NULL;
size_t i = 0;
ssize_t read = 0;
size_t n = 0;
char *found = NULL;
fp = fopen("votes.txt", "r");
/* open the votes file */
if(fp == NULL) {
fprintf(stderr, "Cannot open votes file [ %s ]\n", strerror(errno));
return FALSE;
}
/* fill the structure with candidates */
for(i = 0; i < NUMBER_OF_CANDIDATES;) {
read = getline(&candidate_names[i], &n ,fp);
if(read == -1) {
fprintf(stderr, "Cannot read candidate [ %d ] [ %s ]\n",
i, strerror(errno));
candidate_names[i] = "Invalid candidate";
i++;
continue;
}
/* Just ignore the key work in the text file */
if(strcmp("CANDIDATES\n", candidate_names[i]) != 0) {
/* Find and remove the carriage return */
found = strchr(candidate_names[i], '\n');
if(found != NULL) {
/* Remove the carriage return by nul terminating */
*found = '\0';
}
i++;
}
}
fclose(fp);
return TRUE;
}
EDITAR ========= LIBERAR candidate_names ======
All heap blocks were freed -- no leaks are possible
==4364==
==4364== ERROR SUMMARY: 84 errors from 2 contexts (suppressed: 12 from 8)
==4364==
==4364== 42 errors in context 1 of 2:
==4364== Invalid free()/delete/delete[]
==4364== at 0x40057F6: free (vg_replace_malloc.c:325)
==4364== by 0x8048A95: destroy_candidate (candidate.c:107)
==4364== by 0x8048752: main (driver.c:44)
==4364== Address 0x401e1b8 is 0 bytes inside a block of size 120 free'd
==4364== at 0x40057F6: free (vg_replace_malloc.c:325)
==4364== by 0x8048A95: destroy_candidate (candidate.c:107)
==4364== by 0x8048752: main (driver.c:44)
==4364==
==4364==
==4364== 42 errors in context 2 of 2:
==4364== Invalid read of size 1
==4364== at 0x400730E: strcmp (mc_replace_strmem.c:426)
==4364== by 0x8048A7F: destroy_candidate (candidate.c:106)
==4364== by 0x8048752: main (driver.c:44)
==4364== Address 0x401e1b8 is 0 bytes inside a block of size 120 free'd
==4364== at 0x40057F6: free (vg_replace_malloc.c:325)
==4364== by 0x8048A95: destroy_candidate (candidate.c:107)
==4364== by 0x8048752: main (driver.c:44)
void destroy_candidate()
{
size_t i = 0;
for(i = 0; i < NUMBER_OF_CANDIDATES; i++) {
if(strcmp(candidate_names[i], "Invalid candidate") != 0) {
free(candidate_names[i]);
}
}
}
edición con código de main.c =====================
typedef struct Candidate_data_t {
size_t candidate_data_id;
Candidates_t *candidate;
} Candidate_data;
static Candidate_data* create_candidate_data(Candidates_t *candidate, size_t i);
static void destroy_candidata_data(Candidate_data *cand_data);
int main(void)
{
Candidates_t *candidate = NULL;
Candidate_data *cand_data[NUMBER_OF_CANDIDATES] = {0};
size_t i = 0;
load_candidates();
for(i = 0; i < NUMBER_OF_CANDIDATES; i++) {
candidate = create_candidates(i);
if(candidate == NULL) {
fprintf(stderr, "Cannot failed to initalize candidate [ %d ]\n", i);
}
/* Create array of candidates */
cand_data[i] = create_candidate_data(candidate, i);
fill_candidates(cand_data[i]->candidate);
}
/* Display each candidate */
for(i = 0; i < NUMBER_OF_CANDIDATES; i++) {
display_candidate(cand_data[i]->candidate);
printf("\n");
}
for(i = 0; i < NUMBER_OF_CANDIDATES; i++) {
destroy_candidata_data(cand_data[i]);
}
return 0;
}
static Candidate_data* create_candidate_data(Candidates_t *candidate, size_t id)
{
Candidate_data *cand_data = NULL;
cand_data = malloc(sizeof *cand_data);
if(cand_data == NULL) {
fprintf(stderr, "Failed to allocate memory [ %s ]\n",
strerror(errno));
return NULL;
}
cand_data->candidate_data_id = id;
cand_data->candidate = candidate;
return cand_data;
}
static void destroy_candidata_data(Candidate_data *cand_data)
{
destroy_candidate(cand_data->candidate);
free(cand_data);
}
¡Su actualización, con 'destroy_candidate()' todavía está en error! El error nunca se mostrará con su programa, pero si alguna vez necesita llamar 'load_candidates()' más de una vez * (o más al punto, si necesita 'getline()' para el mismo apuntador candidate_name [i]) * existe la posibilidad de que la biblioteca intente reasignar un puntero no válido. – pmg