在字符串和结构数组中查找动态内存分配错误 [英] finding dynamic memory allocation errors in arrays of strings and structures

查看:64
本文介绍了在字符串和结构数组中查找动态内存分配错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我有一个名为 vitorias 的结构数组(英文, victories),一个结构数组,该结构数组以及一个

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.

结构和数组:

char **sistema_eq;

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

问题是,当我使用 cppcheck 它给出了一条错误消息:

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

而且,如果我使用 Valgrind ,它说我做了10个分配和2个免费,但是我不这样做无法理解问题所在,因为我最终释放了我的所有想法。

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.

程序:

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

推荐答案

正如评论中所指出的,您永远不会免费 for 循环中使用 calloc 分配的数据。在您的主端的末尾附近添加此循环(或类似的东西):

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);
//...

此外,当您使用 calloc ,您不需要任何 memset 通话!从 void * calloc(size_t num,size_t size)的链接文档中:

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 ):


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

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

报告有关 realloc 的错误:如果调用 realloc 失败,则您使用的代码将阻止后续操作释放原始数据(指针中的地址),因为其地址将被 NULL 失败了!为防止这种情况,请使用临时指针,如下所示:

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

最后(我认为),您可能想读以下内容:我是否强制转换malloc的结果?-这对于调用 calloc realloc

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.

这篇关于在字符串和结构数组中查找动态内存分配错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆