erehwyrevemai
erehwyrevemai

Reputation: 17

Using free() for char-pointer in struct

typedef struct inventory 
{
   char *name; 
   int quantity; 
   double price; 
   struct inventory* next_inventory; 
   
} invent;

int main(void)
{
   invent *one=malloc(sizeof(invent)); 
   invent *two=malloc(sizeof(invent));
   invent *three=malloc(sizeof(invent));

   one->next_inventory=two;
   two->next_inventory=three;
   three->next_inventory=NULL;

   one->name=malloc(256);
   ...(repeat two->name, three->name)
   
   printf("name: ");
   scanf("%s", one->name);

   printf("qunatity: ");
   scanf("%d", &one->quantity);

   printf("price: ");
   scanf("%lf", &one->price);
   
   ...(repeat scanf() for two, three)

   while(one!=NULL)
   {
      printf("%s %d %.0f\n", one->name, one->quantity, one->price);
      printf("check\n");
      one=one->next_inventory;
   }

   free(one->name);
   free(two->name);
   free(three->name);
   free(one);
   free(two);
   free(three);

   return 0;

free(one->name); doesn't work. I checked another free(), using printf("check");, two->name, three->name, one ... its worked. Why only free(one->name) doesn't work? What can I do for solve this problem? Give me the advice.

Upvotes: 1

Views: 171

Answers (2)

farbiondriven
farbiondriven

Reputation: 2468

You are using your actual 'one' variable to do the iteration, in the end you are trying to free(one) where one points to NULL.

You should not lose track of the address of the memory you requested to allocate, to be able to release that memory later with free.

I would use a temporary pointer to iterate:

 invent* tmp = one;
 while(tmp!=NULL)
   {
      printf("%s %d %.0f\n", tmp->name, tmp->quantity, tmp->price);
      printf("check\n");
      tmp=tmp->next_inventory;
   }

// free all names and one, two, three.

In alternative:

you can define a function for printing:

void printAll(invent* one)
{
    while(one!=NULL)
   {
      printf("%s %d %.0f\n", one->name, one->quantity, one->price);
      one=one->next_inventory;
   }
}

then in the main, call

printAll(one)

This works as the pointer is passed by value in the function and you won't lose the original address.

Upvotes: 2

pifor
pifor

Reputation: 7882

Here is a improved version of your program that includes also checking malloc return code:

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

typedef struct invent 
{
   char *name; 
   int quantity; 
   double price; 
   struct invent* next_inventory; 
   
} invent;

void enter(invent **s)
{
   printf("name: ");
   scanf("%s", (*s)->name);

   printf("quantity: ");
   scanf("%d", &(*s)->quantity);

   printf("price: ");
   scanf("%lf", &(*s)->price);
   
}

void *alloc(size_t size)
{
    void *p;
    
    p = malloc(size);
    if (p == NULL)
    {
        perror("malloc");
        exit(1);
    }
    return p;
}

int main(void)
{
   invent *start;

   invent *one;
   invent *two;
   invent  *three;

   one = alloc(sizeof(invent)); 
   two = alloc(sizeof(invent));
   three = alloc(sizeof(invent));

   start = one;

   one->next_inventory=two;
   two->next_inventory=three;
   three->next_inventory=NULL;

   one->name=alloc(256);
   two->name=alloc(256);
   three->name=alloc(256);


   enter(&one);
   enter(&two);
   enter(&three);

   while(one != NULL)
   {
      printf("%s %d %.0f\n", one->name, one->quantity, one->price);
      printf("check\n");
      one=one->next_inventory;
   }

   free(start->name);
   free(two->name);
   free(three->name);
   free(start);
   free(two);
   free(three);

   return 0;

}

Upvotes: 1

Related Questions