finding dynamic memory allocation errors in arrays of strings and structures

て烟熏妆下的殇ゞ 提交于 2020-06-17 03:38:07

问题


So, I have an array of a structures called vitorias (in English, "victories"), an array of structures and an array of that structure and an array of strings.

Structure and arrays:

char **sistema_eq;

typedef struct
{
    int id;
    char nome[MAX_CHARS];
    int vit;
} vitorias;

The problem is that when I use cppcheck it gives an error saying:

(error) Common realloc mistake: 'conj_vit' nulled but not freed upon failure
(error) Common realloc mistake: 'sistema_eq' nulled but not freed upon failure
(error) Common realloc mistake: 'conj_jogos' nulled but not freed upon failure

And, if I use Valgrind, it says that I did 10 allocs and 2 free, but I don't understand what's wrong, because I freed everything in the end I think.

Program:

#include<stdlib.h> 
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024 /* max characters of a word */
#define MAX_SIZE 5

static int size_until = 0; /*conts the size of sistema_eq and conj_vit*/
static int line = 1; /* counts the number of lines of the stdin */
int ident = 0; /*conts the id of jogos*/
static int size_until = 0; /*counts the size of sistema_eq*/
static int size_until2 = 0;/*counts the size of conj_jogos*/

void a(char nome_jg[],char team1[],char team2[],int score1,int score2);
void A(char nome[]);

char **sistema_eq;
jogo *conj_jogos;
vitorias *conj_vit;

int main()
{
    char c;
    char nome_jg[MAX_CHARS], team1[MAX_CHARS], team2[MAX_CHARS];
    int score1;
    int score2;
    int i;

    conj_jogos = (jogo*)calloc(MAX_SIZE,sizeof(jogo));
    memset(conj_jogos,0, MAX_SIZE*sizeof(jogo));

    conj_vit = (vitorias*)calloc(MAX_SIZE,sizeof(vitorias));
    memset(conj_vit,0, MAX_SIZE*sizeof(vitorias));

    sistema_eq = (char**)calloc(MAX_SIZE,sizeof(*sistema_eq));
    memset(sistema_eq,0, MAX_SIZE*sizeof(*sistema_eq));

    for(i=0;i<MAX_SIZE;i++)
    {
        sistema_eq[i] = (char*)calloc(1024,sizeof(char));
        memset(sistema_eq[i],0, sizeof(char)*1024);
    }

    while ((c = getchar())!= 'x') {
    switch (c) 
    {
        case 'A':
        {
            scanf("%1023[^:\n]",nome_jg);
            remove_esp(nome_jg);
            A(nome_jg);
            break;
        }
        case 'a':
        {
            scanf("%1023[^:\n]:%1023[^:\n]:%1023[^:\n]:%d:%d",nome_jg,team1,team2,&score1,&score2);
            remove_esp(nome_jg);
            a(nome_jg,team1,team2,score1,score2);
            line++;
            break;
        }
    }
    }
    free(conj_vit);
    free(conj_jogos);
    free(sistema_eq);
   return 0;
}

/*This functions adds a victory and a equipa (team in english) into the corresponding arrays and updates the vitories of each team*/

//Example in El Classico Barcelona vs Real Madrid 1:0, which means Barcelona won

void A(char nome[])
{
    if (nome_in_sis(nome) == 1)
    {
        printf("%d Equipa existente.\n",line);
        line++;
    }
    else
    {
        if (size_until < MAX_SIZE)
        {
            strcpy(sistema_eq[size_until],nome);
            strcpy(conj_vit[size_until].nome,nome);
            conj_vit[size_until].id = size_until;
            size_until++;
            line++;
        }
        else
        {
            conj_vit = realloc(conj_vit,sizeof(vitorias)*(size_until+1));
            sistema_eq = realloc(sistema_eq,sizeof(char*)*(size_until+1));
            sistema_eq[size_until] = calloc(1024,sizeof(char*));
            strcpy(sistema_eq[size_until],nome);
            strcpy(conj_vit[size_until].nome,nome);
            conj_vit[size_until].id = size_until;
            size_until++;
            line++;

        }
    }
}


/*This functions adds a jogo (game in english) and a equipa (team in english) into the array conj_jogos (the array of jogos)*/

void a(char nome_jg[],char team1[],char team2[],int score1,int score2)
{
    int vit;
    if (jogo_in(nome_jg) == 1)
    {
        printf("%d Jogo existente.\n",line);
        line++;
    }
    else if ((nome_in_sis(team1) == 0) || (nome_in_sis(team2) == 0))
        {
        printf("%d Equipa inexistente.\n",line);
        line++;
    }
    else
    {
        if (size_until2 < MAX_SIZE)
        {
            conj_jogos[size_until2] = cria_jogo(nome_jg,team1,team2,score1,score2);
            if (score1 > score2)
            {
                vit = procura_vit(team1);
                conj_vit[vit].vit++;
            }
            else
            {
                vit = procura_vit(team2);
                conj_vit[vit].vit++;  
            }
            size_until2++;
        }
        else
        {
            size_until2++;
            conj_jogos = realloc(conj_jogos,sizeof(jogo)*(size_until2+1));
            conj_jogos[size_until2] = cria_jogo(nome_jg,team1,team2,score1,score2);
            if (score1 > score2)
            {
                vit = procura_vit(team1);
                conj_vit[vit].vit++;
            }
            else
            {
                vit = procura_vit(team2);
                conj_vit[vit].vit++;  
            }
            size_until2++;
        }
    }
}

Sorry if the code looks messy and thanks for the help.


回答1:


As pointed out in the comments, you never free the data you allocated with calloc in the for loop. Add this loop (or something very similar) near the end of your main:

//...
    for(i=0;i<MAX_SIZE;i++) free(sistema_eq[i]); // MUST be before the next line!
    free(sistema_eq);
//...

Also, as you use calloc, you don't need any of the memset calls! From the linked documentation for void* calloc( size_t num, size_t size ):

Allocates memory for an array of num objects of size and initializes all bytes in the allocated storage to zero.

For the 'errors' reported concerning realloc: in cases where a call to realloc fails, the code you use will prevent subsequent freeing of the original data (the address of which was in the pointer), as its address will be replaced with NULL on such a failure! To prevent this, use a temporary pointer, like this:

    jogo* temp_jogo = realloc(conj_jogos,sizeof(jogo)*(size_until2+1));
    if (temp_jogo != NULL) conj_jogos = temp_jogo; 
    else {
    //  In case of failure, we now still have the original conj_jogos
    //  pointer, which we can then pass to "free" at some point, presumably
    //  after we've signalled and/or handled the allocation error.
    }

Finally (I think), you may like to read this: Do I cast the result of malloc? - which is equally valid for calls to calloc and realloc.



来源:https://stackoverflow.com/questions/61782351/finding-dynamic-memory-allocation-errors-in-arrays-of-strings-and-structures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!