-4

I have a structure:

struct student{
    int roll_no;
    char *name = malloc(25 * sizeof(char));;
    char *phone_no = malloc(10 * sizeof(char));;
    char *dob = malloc(10 * sizeof(char));;
}*s1;

int main(){
    s1 = malloc(5 * sizeof(student)); //array of student
    //.....
}

What is appropriate code for the complete loop for allocating an array of student of size 'n' and then de-allocating it afterwards? Note: The question here deals with allocation and de-allocation of elements of the instance of a structure.

  • 4
    That's not valid C code. You can't do a `malloc` in a structure member declaration. Also, it's recommended that you [*do not cast the return of `malloc`*](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc?s=1|279.0271). – lurker Nov 03 '17 at 16:24
  • What's your question? – ForceBru Nov 03 '17 at 16:24
  • then [`free`](https://linux.die.net/man/3/free) them.. what's the question? In general, you want to `free` items in a "mirror image" from how you `malloc`ed them. That is, the last items you `malloc`ed should be freed first... like a LIFO stack. But it entirely depends on the particular situation of course. – yano Nov 03 '17 at 16:24
  • 1
    "And after executing my code" - I'm afraid that code won't compile at all – asio_guy Nov 03 '17 at 16:57
  • Possible duplicate of [How do I free memory in C?](https://stackoverflow.com/questions/9069205/how-do-i-free-memory-in-c) – ordonezalex Nov 03 '17 at 17:12

4 Answers4

1

This...

typedef struct student{
    int roll_no;    // (the following illegal syntax commented out)
    char *name;     // = malloc(25 * sizeof(char));;
    char *phone_no; // = malloc(10 * sizeof(char));;
    char *dob;      // = malloc(10 * sizeof(char));;
}*s1;

...from what is being described as the need, (minus the illegal assignment statements) could probably better be formed as:

typedef struct {
    int roll_no;
    char *name;    //needs memory
    char *phone;   //needs memory
    char *dob;     //needs memory
}STUDENT;          

Then, use the new variable type: STUDENT, to create the instances of the struct as needed. Your OP indicates you need 5:

STUDENT s[5];     //Although this array needs no memory, the 
                  //members referenced by it do 
                  //(as indicated above)

Now, all that is necessary is to create memory for the 3 members that require it, in each of the 5 instances.

for(i=0;i<5;i++)
{
    s[i].name  = calloc(80, 1); //calloc creates AND initializes memory.
    s[i].phone = calloc(20, 1); //therefore safer than malloc IMO.
    s[i].dob   = calloc(20, 1); //Also, change values as needed to support actual
                                //length needs for name, phone and dob
}
// Use the string members of s[i] as you would any other string, But do not
// forget to free them when no longer needed.
...
for(i=0;i<5;i++)
{
    free(s[i].name);
    free(s[i].phone);
    free(s[i].dob);
}

Note, because of the way the array s is created in this example, i.e. with memory on the stack instead of the heap, there is no need to free it.

One other note, the example code above focused on a method to create memory for the char * members of your struct array, but when actually coding for keeps, the return of [m][c][re]alloc should always be checked that memory was created before trying to use the variable. For example:

s[i].name  = calloc(80, 1);
if(!s[i].name) //checking that memory was created
{
    ;//if failed, then handle error.
}
...
ryyker
  • 22,849
  • 3
  • 43
  • 87
1

In addition to ryyker's answer, if you want to do it dynamically:

#include <stdlib.h>

struct student{
    int roll_no;
    char *name;
    char *phone;
    char *dob;
};

int main()
{
    int i, student_count = 5;
    struct student ** s = malloc(sizeof(struct student *) * student_count);

    if (s)
    {
        for (i = 0; i < student_count; ++i)
        {
            s[i] = malloc(sizeof(struct student));

            if (s[i])
            {
                //set up student's members
            }
        }

        for (i = 0; i < student_count; ++i)
        {
            //free student's members before the next line.
            free(s[i]);
        }

        free(s);
    }

    return 0;
}
Millie Smith
  • 4,536
  • 2
  • 24
  • 60
0

You must free everything you malloc, and as mentioned in the comments you cannot malloc inside the struct.

#include <stdio.h>
#include <stdlib.h>

#define NUM_STUDENTS 5

struct student{
    int roll_no;
    char *name;
    char *phone;
    char *dob;
};

int main(void)
{
  int i;
  // if this was me, I would simply replace this with
  // struct student s[NUM_STUDENTS];, but the goal here is to illustrate
  // malloc and free
  struct student* s = malloc(sizeof(struct student) * NUM_STUDENTS);
  if (s == NULL)  // handle error

  for (i=0; i<NUM_STUDENTS; i++)
  {
    // sizeof(char) is guaranteed to be 1, so it can be left out
    s[i].name = malloc(25);
    if (s[i].name == NULL) // handle error
    s[i].phone = malloc(10);
    if (s[i].phone == NULL) // handle error
    s[i].dob = malloc(10);
    if (s[i].dob == NULL) // handle error
  }

  // do stuff with with the data
  ....

  // time to clean up, free in the reverse order from malloc
  for (i=0; i<NUM_STUDENTS; i++)
  {
    // the dob, phone, name order here isn't important, just make sure you
    // free each struct member before freeing the struct
    free(s[i].dob);
    free(s[i].phone);
    free(s[i].name);
  }

  // now that all the members are freed, we can safely free s
  free(s);

  return 0;
}
yano
  • 4,827
  • 2
  • 23
  • 35
0

User Abhijit gave an answser that was in the right direction, but not complete. His answer should have been:

typedef struct STUDENT{
    int roll_no;
    char *name;
    char *phone;
    char *dob;
}student;

void example(int n_students)
{
    student **s;
    int i;

    s= malloc(n_students * sizeof(student *));
    for (i=0; i<n_students; i++)
    {
        s[i]= malloc(sizeof(student));
        s[i]->name= malloc(25);
        s[i]->phone= malloc(10);
        s[i]->dob= malloc(10);
    }
    // now free it:
    for (i=0; i<n_students; i++)
    {
        free(s[i]->name);
        free(s[i]->phone);
        free(s[i]->dob);
        free(s[i]);
    }
    free(s);
}
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41