寻找字符串和结构数组中的动态内存分配错误。

问题描述 投票:0回答:1

所以,我有一个数组的结构,叫做 vitorias 英文为 "victories"),一个结构的数组和该结构的数组以及一个字符串的数组。

结构和数组。

char **sistema_eq;

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

问题是,当我使用 cppcheck 它给出了一个错误的说法。

(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

而且,如果我使用 Valgrind它说我做了10个分配和2个释放,但我不明白有什么问题,因为我认为最后我释放了所有的东西。

程序。

#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++;
        }
    }
}

很抱歉,如果代码看起来很乱,谢谢你的帮助。

c arrays pointers dynamic-memory-allocation
1个回答
1
投票

正如评论中指出的那样,你从来没有 free 的数据,您用 callocfor 循环。将这个循环(或类似的循环)添加到你的 main:

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

另外,当你使用 calloc,你不需要任何的 memset 调用! 从链接的文档中可以看到 void* calloc( size_t num, size_t size ):

为大小为num的对象数组分配内存,并将分配的内存中的所有字节初始化为零。

报告的 "错误 "涉及 realloc呼叫:在呼叫的情况下 realloc 失败,您使用的代码将阻止后续释放的 原有 数据 指针中的),因为它的地址将被替换为 NULL 在这样的失败中!为了防止这种情况发生,可以使用临时指针,像这样: 为了防止这种情况发生,可以使用一个临时指针,像这样。

    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.
    }

最后(我想),你可能会喜欢读这个: 我是否要投掷malloc的结果? - 的结果,这对调用 callocrealloc.

© www.soinside.com 2019 - 2024. All rights reserved.