Home > other >  how to free memory in c in this context
how to free memory in c in this context

Time:10-14

context: Create a student record using structures and pointers in C language

#define MAXS    200
typedef struct student{
    int id;
    char *name;
    int age;
    float gpa;
}student;

int main(int argc,char **argv)
{
    if(argc < 2){
        fprintf(stderr,"ERROR: filename csv. please\n");
        exit(EXIT_FAILURE);
    }
    char *line = NULL;   /* pointer to use with getline ()   */
    ssize_t read = 0;    /* characters read by getline ()    */
    size_t n = 0;        /* number of bytes to allocate      */
    char *p = NULL;      /* pointer to use parsing line      */
    char *sp = NULL;      /* 2nd pointer to use parsing line      */
    int field = 0;
    int cnt = 0;         /* counter for number allocated     */
    student **students = NULL;  /* ptr to array of stuct student    */
    int it = 0;

    FILE *fp = fopen(argv[1],"r");
    if(!fp){
        fprintf(stderr,"failed to open file for reading\n");
        exit(EXIT_FAILURE);
    }

    students = calloc(MAXS, sizeof(*students));
    if(!students){
        fprintf(stderr,"calloc failed to allocate\n");
        exit(EXIT_FAILURE);
    }
    // 2158,John Q. Student,11,88.42
    while((read = getline(&line,&n,fp)) != -1){
        sp = p = line;
        field = 0;

        students[cnt] = malloc(sizeof(**students));
        if(!students[cnt]){
            fprintf(stderr,"malloc failed to allocate students\n");
            exit(EXIT_FAILURE);
        }

        while(*p){
            if(*p == ',')
            {
                *p = 0;
                if(field == 0) students[cnt]->id  = atoi(sp);
                if(field == 1) students[cnt]->name  = strdup(sp);
                if(field == 2) students[cnt]->age = atoi(sp);

                *p = ',';
                sp = p 1;
                field  ;
            }
            p  ;
        }
        students[cnt]->gpa = strtof(sp,NULL);
        cnt   ;
        if(cnt == MAXS){
            fprintf(stderr,"ERROR: MAXS reached\n");
            break;
        }
    }
    printf("cnt = %d\n",cnt);
    /* iterate over all students and print */
    printf("\nThe students in the class are: \n\n");
    while(students[it]){
        printf(" %d %s %d %6.2f\n"
            ,students[it]->id,students[it]->name,students[it]->age,students[it]->gpa);
        it  ;
    }

    int total = it;
    printf("\nTotal number of students: %d\n",total);

    /* compute average age and gpa*/
    float avg_age = 0;
    float avg_gpa = 0;

    for(it = 0; it < total; it  )
    {
        avg_age  = (float) students[it]->age;
        avg_gpa  = (float) students[it]->gpa;
    }
    avg_age /= (float) total;
    avg_gpa /= (float) total;

    printf("Average Age of students: %.2f\n",avg_age);
    printf("Average GPA of students: %.2f\n",avg_gpa);

    for(it = 0; it < MAXS; it  ){
        free(students[it]);
    }
    free(students);

    exit(EXIT_SUCCESS);
}

valgrind command output:

==567070==
==567070== HEAP SUMMARY:
==567070==     in use at exit: 672 bytes in 7 blocks
==567070==   total heap usage: 15 allocs, 8 frees, 7,512 bytes allocated
==567070==
==567070== 80 bytes in 5 blocks are definitely lost in loss record 1 of 3
==567070==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==567070==    by 0x491560E: strdup (strdup.c:42)
==567070==    by 0x1094B4: main (in /home/jian/helloc/a.out)
==567070==
==567070== 120 bytes in 1 blocks are still reachable in loss record 2 of 3
==567070==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==567070==    by 0x48ED1A2: getdelim (iogetdelim.c:62)
==567070==    by 0x109261: main (in /home/jian/helloc/a.out)
==567070==
==567070== 472 bytes in 1 blocks are still reachable in loss record 3 of 3
==567070==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==567070==    by 0x48EC6CD: __fopen_internal (iofopen.c:65)
==567070==    by 0x48EC6CD: fopen@@GLIBC_2.2.5 (iofopen.c:86)
==567070==    by 0x10920C: main (in /home/jian/helloc/a.out)
==567070==
==567070== LEAK SUMMARY:
==567070==    definitely lost: 80 bytes in 5 blocks
==567070==    indirectly lost: 0 bytes in 0 blocks
==567070==      possibly lost: 0 bytes in 0 blocks
==567070==    still reachable: 592 bytes in 2 blocks
==567070==         suppressed: 0 bytes in 0 blocks
==567070==
==567070== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

If i PUT free(students[it]->name); In the last for loop, then it will Segmentation fault (core dumped) . How can I free all the memory in this context?

CodePudding user response:

  1. Changed MAXS to cnt in the loop where you free students, and added a free of the name.
    for(it = 0; it < cnt; it  ){
        free(students[it]->name);
        free(students[it]);
    }
  1. getline() allocates line, so free that in loop and each exit point.
  2. Initialized name in case the field is missing (@SupportUkraine).
  3. fclose(fp) after the loop that reads the file
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXS 100

typedef struct student{
    int id;
    char *name;
    int age;
    float gpa;
}student;

int main(int argc,char **argv)
{
    if(argc < 2){
        fprintf(stderr,"ERROR: filename csv. please\n");
        exit(EXIT_FAILURE);
    }
    char *line = NULL;   /* pointer to use with getline ()   */
    ssize_t read = 0;    /* characters read by getline ()    */
    size_t n = 0;        /* number of bytes to allocate      */
    char *p = NULL;      /* pointer to use parsing line      */
    char *sp = NULL;      /* 2nd pointer to use parsing line      */
    int field = 0;
    int cnt = 0;         /* counter for number allocated     */
    student **students = NULL;  /* ptr to array of stuct student    */
    int it = 0;

    FILE *fp = fopen(argv[1],"r");
    if(!fp){
        fprintf(stderr,"failed to open file for reading\n");
        exit(EXIT_FAILURE);
    }

    students = calloc(MAXS, sizeof(*students));
    if(!students){
        fprintf(stderr,"calloc failed to allocate\n");
        exit(EXIT_FAILURE);
    }
    // 2158,John Q. Student,11,88.42
    while((read = getline(&line,&n,fp)) != -1){
        sp = p = line;
        field = 0;

        students[cnt] = malloc(sizeof(**students));
        if(!students[cnt]){
            fprintf(stderr,"malloc failed to allocate students\n");
            free(line);
            exit(EXIT_FAILURE);
        }

        students[cnt]->name = NULL;
        while(*p){
            if(*p == ',')
            {
                *p = 0;
                if(field == 0) students[cnt]->id  = atoi(sp);
                if(field == 1) students[cnt]->name = strdup(sp);
                if(field == 2) students[cnt]->age = atoi(sp);

                *p = ',';
                sp = p 1;
                field  ;
            }
            p  ;
        }
        students[cnt]->gpa = strtof(sp,NULL);
        cnt   ;
        if(cnt == MAXS){
            fprintf(stderr,"ERROR: MAXS reached\n");
            break;
        }
    }
    fclose(fp);
    free(line);

    printf("cnt = %d\n",cnt);
    /* iterate over all students and print */
    printf("\nThe students in the class are: \n\n");
    while(students[it]){
        printf(" %d %s %d %6.2f\n"
            ,students[it]->id,students[it]->name,students[it]->age,students[it]->gpa);
        it  ;
    }

    int total = it;
    printf("\nTotal number of students: %d\n",total);

    /* compute average age and gpa*/
    float avg_age = 0;
    float avg_gpa = 0;

    for(it = 0; it < total; it  )
    {
        avg_age  = (float) students[it]->age;
        avg_gpa  = (float) students[it]->gpa;
    }
    avg_age /= (float) total;
    avg_gpa /= (float) total;

    printf("Average Age of students: %.2f\n",avg_age);
    printf("Average GPA of students: %.2f\n",avg_gpa);

    for(it = 0; it < cnt; it  ){
        free(students[it]->name);
        free(students[it]);
    }
    free(students);
    exit(EXIT_SUCCESS);
}

and valgrind hates us less:

==1387007== HEAP SUMMARY:
==1387007==     in use at exit: 0 bytes in 0 blocks
==1387007==   total heap usage: 21 allocs, 28 frees, 6,798 bytes allocated
==1387007==                                                                                                            
==1387007== All heap blocks were freed -- no leaks are possible                                                        
  • Related