1

I'd like to extend my array containing a struct 'Article' using realloc, so I tell realloc to take the old array and extend it then I add my new Article to the new array but this doesn't work and i can't find the problem. this is the error message >corrupted size vs. prev_size Abandon (core dumped)

typedef struct
{
    char ref[6];
    float pu;
    int qt;
    char desi[31];
}Article;

void global(void)
{
    FILE * fe;
    Article *tart,l;
    int nbart;
    fe=fopen("a.txt","a+");
    tart=chargeFarticle(fe,&nbart);
    Showtart(tart,nbart);

    printf("Ref: ");
    scanf("%s",l.ref);
    printf("pu: ");
    scanf("%f",&l.pu);
    printf("qt: ");
    scanf("%d%*c",&l.qt);
    printf("Desi: ");
    fgets(l.desi,31,stdin);
    l.desi[strlen(l.desi) -1]='\0';
    
    tart=AddArt(l,tart,&nbart);

    Showtart(tart,nbart);

    fclose(fe);
}
Article readArt(FILE * fe)
{
    Article a;
    fscanf(fe,"%s%f%d",a.ref,&a.pu,&a.qt);
    fgets(a.desi,31,fe);
    a.desi[strlen(a.desi) - 1]='\0';
    return a;
}

Article * chargeFarticle(FILE*fe,int *nbart)
{
    Article *tart;
    int i;
    fscanf(fe,"%d",nbart);
    tart=(Article *)malloc(*nbart*sizeof(Article));
    if(tart==NULL)
    {
        printf("Pb Malloc\n");
        exit(1);
    }
    for(i=0;i<*nbart;i++)
        tart[i]=readArt(fe);
    return tart;
}

Article * AddArt(Article l,Article *tart,int *nbart)
{
    int i;
    Article *aux;
    aux=(Article *)realloc(tart,*nbart*sizeof(Article));
    free(tart);
    tart=aux;
    tart[*nbart]=l;
    *nbart+=1;
    return tart;
}
Zipen
  • 15
  • 5
  • *How* doesn't the code work? What happens when you build it with extra warning enabled? What happens when you run it? Have you tried to catch any possible crash with a debugger to see when and where in your code it happens? – Some programmer dude Dec 05 '21 at 12:41
  • When you pass the array to a function the function gets a copy of the pointer, any `realloc()` inside the function is not refelected on the pointer the callee has. – pmg Dec 05 '21 at 12:42
  • And more importantly, how do you call the `AddArt` function? What do you do with the pointer it returns? Please [edit] your question to include a proper [mre]. – Some programmer dude Dec 05 '21 at 12:42
  • 1
    Why do you call `free(tart)` after the `realloc` call? – G.M. Dec 05 '21 at 12:49
  • @G.M. I thought it would free the old 'tart' array since i wouldn't need it anymore because realloc will create a new one – Zipen Dec 05 '21 at 13:01
  • @chux-ReinstateMonica You're right i had to increment *nbart before allocation. I also use fgets() because 'desi' contains a sentence with multiple spaces. – Zipen Dec 05 '21 at 13:01
  • @Zipen Using `fgets()` is not the issue. `l.desi[strlen(l.desi) -1]='\0';` is the problem. Who or what text suggested that? – chux - Reinstate Monica Dec 05 '21 at 13:03
  • @chux-ReinstateMonica my current university teacher only showed me `l.desi[strlen(l.desi) -1]='\0';` I also haven't seen `strcspn` yet. – Zipen Dec 05 '21 at 13:06
  • @Zipen Editied `tart[*nbart]=l;` is still a problem. – chux - Reinstate Monica Dec 05 '21 at 13:06
  • @Zipen _University teacher_ is not teaching best practices. [Removing trailing newline character from fgets() input](https://stackoverflow.com/q/2693776/2410359). "I also haven't seen strcspn yet." implies that using that in an answer is unacceptable. If that is so, post all answer limitations in the question, else assume good answer will use all of C. – chux - Reinstate Monica Dec 05 '21 at 13:08
  • @chux-ReinstateMonica no worries you can use all of C I am here to learn – Zipen Dec 05 '21 at 13:13
  • @chux-ReinstateMonica you're right `tart[*nbart]=l;` doesn't increment my struct l, I forgot to add -1 at the end `tart[*nbart-1]=l;` . thank you – Zipen Dec 05 '21 at 13:21

2 Answers2

0

At least these problems:

Bad free()

When realloc() works, not need to free(old pointer). In fact, realloc() may return the same pointer.

aux=(Article *)realloc(tart,*nbart*sizeof(Article));
// free(tart);

Better to test for allocation success and drop the unnecessary casts.

if (*nbart < 0) {
  // Handle error
}

aux = realloc(tart,sizeof *tart * *nbart);
if (aus == NULL && *nbart > 0) {
  // Handle error
}

Out of range

tart[*nbart]=l; accesses tart[*nbart] out of its range.

Unsafe zeroing

l.desi[strlen(l.desi) -1]='\0'; does not certainly lop of the trailing '\n'. '\n' might not exist, fgets() may have failed, with nefarious input strlen(l.desi) may be 0.

Better as l.desi[strcspn(l.desi, "\n")] = '\0'

Other issues?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0
    a.desi[strlen(a.desi) - 1]='\0';
char *removeNewLine(char *c)
{
    char *wrk = c;
    if(c)
    {
        while(*wrk) wrk++;
        if(wrk - c)
        {
            if(wrk[-1] == '\n') wrk[-1] = 0;
        }
    }
    return c;
}

Many other errors - listed by @chux.

I would implement is other way:

typedef struct
{
    char ref[6];
    float pu;
    int qt;
    char desi[31];
}Article;

typedef struct
{
    size_t nArticles;
    Article articles[];
}Articles_db;



Articles_db *readArt(Articles_db *art, FILE *fe)
{
    size_t newsize = art ? art -> nArticles + 1 : 1;
    art = realloc(art, sizeof(*art) + sizeof(art -> articles[0]) * newsize);
    if(art)
    {
        Article *a = art -> articles + newsize - 1;
        fscanf(fe,"%s%f%d", a -> ref, &a -> pu, &a -> qt);
        fgets(a -> desi,31,fe);
        /* check the results of the I/O functions */
        art -> nArticles = newsize;
    }
    return art;
}

Articles_db *chargeFarticle(FILE*fe,int *nbart)
{
    Articles_db *tart = NULL, *tmp;
    int i;
    fscanf(fe,"%d",nbart);
    /* check the result of fscanf */
    for(i=0;i<*nbart;i++)
    {
        tmp = readArt(tart, fe);
        if(!tmp)
        {
            printf("Memory allocation error\n");
            break;
        }
        tart = tmp;
    }
    return tart;
}
0___________
  • 60,014
  • 4
  • 34
  • 74