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:
- Changed
MAXS
tocnt
in the loop where you free students, and added a free of thename
.
for(it = 0; it < cnt; it ){
free(students[it]->name);
free(students[it]);
}
getline()
allocates line, so free that in loop and each exit point.- Initialized name in case the field is missing (@SupportUkraine).
- 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