Thread: Question about the free() function?

  1. #1
    Registered User
    Join Date
    May 2020
    Posts
    13

    Question about the free() function?

    After allocating a single large block of memory with the specified size using malloc function, then you use the free() function to deallocate that single large block of memory.

    There is this one confusion. See code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        int *ptr; //This pointer will hold the base address of the block created
        int n, i;
    
    
        if(ptr == NULL)
        {
           printf("Memory not allocated\n");
        }
    
    
        printf("Enter the number of elements for the array: ");
        scanf("%i", &n);
    
    
        // Dynamically allocate memory using malloc()
        ptr = (int*)malloc(n * sizeof(int));
    
    
        // Check if the memory has been successfully allocated by malloc or not
        if(ptr == NULL)
        {
           printf("Memory not allocated\n");
           exit(0);
        } 
        else
        {
           printf("\nMemory successfully allocated using malloc\n");
           printf("Value of *ptr: %i\n", *ptr);
           printf("Address of ptr: %p\n", ptr);
           printf("Size of *ptr: %li\n\n", sizeof(*ptr));
    
    
           // Get the elements of the array
           printf("Initial elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%d, ", ptr[i]);
    
    
           printf("\n\n");
    
    
           // Get the addresses of each of the elements in the array
           printf("Addresses of each elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%p, ", &ptr[i]);
    
    
           printf("\n\nInitializing some values for the first few arrays:\n");
           ptr[0] = 10;
           ptr[1] = 100;
           ptr[2] = 5000;
    
    
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%d, ", ptr[i]);
    
    
           printf("\n\n");
    
    
           printf("Addresses of each elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%p, ", &ptr[i]);
    
    
           printf("\n\nReinitializing some values for the first few arrays:\n");
           ptr[0] = 20;
    
    
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%d, ", ptr[i]);
    
    
           printf("\n\n");
    
    
           printf("Addresses of each elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%p, ", &ptr[i]);
    
    
           printf("\n\n");
    
    
           printf("Size of each Element in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%li, ",sizeof(ptr[i]));
    
    
           free(ptr);
           printf("\n\nFreeing ptr: \n");
    
    
           printf("Size of each Element in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%li, ",sizeof(ptr[i]));
    
    
           printf("\n\n");
    
    
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%d, ", ptr[i]);
    
    
           printf("\n\nSize of *ptr: %li\n\n", sizeof(*ptr));
        }
    
    
        return 0;
    }
    The output is as follows:
    Code:
    Enter the number of elements for the array: 5
    
    
    Memory successfully allocated using malloc
    Value of *ptr: 0
    Address of ptr: 0x55e7db3c0ac0
    Size of *ptr: 4
    
    
    Initial elements in ptr: 
    0, 0, 0, 0, 0, 
    
    
    Addresses of each elements in ptr: 
    0x55e7db3c0ac0, 0x55e7db3c0ac4, 0x55e7db3c0ac8, 0x55e7db3c0acc, 0x55e7db3c0ad0, 
    
    
    Initializing some values for the first few arrays:
    Elements in ptr: 
    10, 100, 5000, 0, 0, 
    
    
    Addresses of each elements in ptr: 
    0x55e7db3c0ac0, 0x55e7db3c0ac4, 0x55e7db3c0ac8, 0x55e7db3c0acc, 0x55e7db3c0ad0, 
    
    
    Reinitializing some values for the first few arrays:
    Elements in ptr: 
    20, 100, 5000, 0, 0, 
    
    
    Addresses of each elements in ptr: 
    0x55e7db3c0ac0, 0x55e7db3c0ac4, 0x55e7db3c0ac8, 0x55e7db3c0acc, 0x55e7db3c0ad0, 
    
    
    Size of each Element in ptr: 
    4, 4, 4, 4, 4, 
    
    
    Freeing ptr: 
    Size of each Element in ptr: 
    4, 4, 4, 4, 4, 
    
    
    Elements in ptr: 
    0, 0, -616824816, 21991, 0, 
    
    
    Size of *ptr: 4
    When using the free() function, it clears the values within ptr there are values such as -616824816, 21991 instead of all 0. I am confused as to how free() works? How does de-allocating memory work in C?

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,084
    Code:
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
        int *ptr; //This pointer will hold the base address of the block created
        int n, i;
     
        //// since ptr has not been initialized (to NULL, for instance)
        //// it could contain any value and so will not necessarily be NULL here.
        if (ptr == NULL)
        {
           printf("Memory not allocated\n");
        }
     
        //// We normally use %d to read a decimal value instead of %i.
        //// You can look up the difference in your reference material.
        printf("Enter the number of elements for the array: ");
        scanf("%i", &n);
     
        // Dynamically allocate memory using malloc()
        ptr = (int*)malloc(n * sizeof(int));
        //// There's no need for the typecast (int*) (if you are compiling as C)
        //// We would usually write this as:
        //// ptr = malloc(n * sizeof *ptr);
     
        // Check if the memory has been successfully allocated by malloc or not
        if(ptr == NULL)
        {
           printf("Memory not allocated\n");
           exit(0);
        } 
        
        //// There's no need for the 'else' and indention here since
        //// the if block exits the program.
        else
        {
           printf("\nMemory successfully allocated using malloc\n");
           printf("Value of *ptr: %i\n", *ptr);
           //// You should cast the pointer to (void*)
           //// since that's what %p expects.
           printf("Address of ptr: %p\n", ptr);
           //// Again, decent people use %d instead of %i :-)
           printf("Size of *ptr: %li\n\n", sizeof(*ptr));
     
           // Get the elements of the array
           printf("Initial elements in ptr: \n");
           //// In modern C we tend to declare the index variable inside
           //// the for loop head like:
           //// for (int i = 0; ....)
           //// It is old practice to declare all your variables at the
           //// top of the function block.
           //// Now we declare them close to where they are first used.
           for(i = 0; i < n; ++i)
               printf("%d, ", ptr[i]);
           printf("\n\n");
     
           // Get the addresses of each of the elements in the array
           printf("Addresses of each elements in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%p, ", &ptr[i]);
     
           printf("\n\nInitializing some values for the first few arrays:\n");
           ptr[0] = 10;
           ptr[1] = 100;
           ptr[2] = 5000;
     
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%d, ", ptr[i]);
           printf("\n\n");
     
           //// Didn't you already do this? 
           printf("Addresses of each elements in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%p, ", &ptr[i]);
     
           //// Presumably you mean "elements" not "arrays". 
           printf("\n\nReinitializing some values for the first few arrays:\n");
           ptr[0] = 20;
     
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%d, ", ptr[i]);
           printf("\n\n");
     
           //// How many times are you going to do this?
           printf("Addresses of each elements in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%p, ", &ptr[i]);
           printf("\n\n");
     
           //// Do you really expect this to change?
           printf("Size of each Element in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%li, ",sizeof(ptr[i]));
     
           free(ptr);
           printf("\n\nFreeing ptr: \n");
     
           //// (*sigh*)
           printf("Size of each Element in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%li, ",sizeof(ptr[i]));
           printf("\n\n");
    
    
           //// When freeing memory, the allocation routine does not zero it.
           //// It merely makes it available for reuse.
           //// As part of it's operation it may write some data to it for it's own purposes.
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
               printf("%d, ", ptr[i]);
     
           printf("\n\nSize of *ptr: %li\n\n", sizeof(*ptr));
        }
     
        return 0;
    }
    The following should show that most values are unchanged, although the first few may be modified as part of the operation of the memory allocation routine.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
     
    #define SIZE 20
     
    int main()
    {
        int *p = malloc(SIZE * sizeof *p);
     
        // load with 10, 20, ..., 200
        for (int i = 0; i < SIZE; ++i)
            p[i] = i * 10 + 10;
     
        for (int i = 0; i < SIZE; ++i)
            printf("%d ", p[i]);
        putchar('\n');
     
        free(p);
     
        for (int i = 0; i < SIZE; ++i)
            printf("%d ", p[i]);
        putchar('\n');
     
        return 0;
    }
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    490

    Post

    Code:
           
           free(ptr);
           printf("\n\nFreeing ptr: \n");
    
           /* not sure whether this is allowed or not. sizeof() is a compile
               time operator rather than function, so it is probably OK */
           printf("Size of each Element in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%li, ",sizeof(ptr[i]));
    
    
           printf("\n\n");
    
           /* This however is definitely not allowed. You can't use a pointer
               after you free it. If you don't do any further allocations,
               you'll probably get back what you left in the buffer, at least on
               a small system. But sometimes the memory is shredded, somtimes
               it is marked as "inaccessible" and the program will crash out. In
               other words it's undefined behaviour */
           printf("Elements in ptr: \n");
           for(i = 0; i < n; ++i)
          printf("%d, ", ptr[i]);
    Last edited by Malcolm McLean; 01-12-2021 at 03:05 PM.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,084
    Malcolm makes a very important point that I totally forgot about.
    It is "undefined behavior" to use a pointer to access memory that has been freed.
    In principle, anything can happen.
    The best argument against democracy is a five minute conversation with the average voter. - Churchill

  5. #5
    Registered User
    Join Date
    May 2020
    Posts
    13
    Quote Originally Posted by Malcolm McLean View Post
    Addresses of each elements in ptr:
    I only repeated this part just to make sure that when adding elements to ptr, the addresses didn't change.

    Quote Originally Posted by Malcolm McLean View Post
    //// Do you really expect this to change?
    I was just making sure each element had the same number of bytes allocated to it. I also did it again just to see if the size changes once you free the ptr pointer.

    Quote Originally Posted by Malcolm McLean View Post
    //// It is old practice to declare all your variables at the
    //// top of the function block.
    //// Now we declare them close to where they are first used.
    Normally, I would do this:
    for(int i = 0; i < n; ++i)


    Just to remind you that I'm a total noob at the C language and trying to understand dynamic memory allocation. So dynamic memory allocation is similar to assigning values to an array, the only difference being that with memory allocation, you can add and delete elements while for an array, it's fixed, you cannot add or delete elements, you can only change element values?

  6. #6
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    798
    Quote Originally Posted by RicsterB View Post
    Just to remind you that I'm a total noob at the C language and trying to understand dynamic memory allocation.

    So dynamic memory allocation is similar to assigning values to an array, the only difference being that with memory allocation, you can add and delete elements while for an array, it's fixed, you cannot add or delete elements, you can only change element values?
    "Dynamic Memory Allocation" functions such as malloc() and calloc() allocate memory from the "Heap" for use by the program. They have nothing to do with assigning any data to the allocated memory.
    realloc() can be used to change the size of the previously dynamically allocated memory.
    free() is used to release the allocated memory. The pointer to the now freed up memory should be immediately nulled so the freed memory can no longer be accessed.

    The size of a real array is a fixed size when the array is created, and cannot be changed.

    Please view "man malloc", and a good up to date book on the C Programming Language for more information on the use of dynamic memory allocation.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. When it is necessary to use the free function?
    By deathslice in forum C Programming
    Replies: 1
    Last Post: 02-29-2016, 10:09 AM
  2. Using free() function
    By heinz55 in forum C Programming
    Replies: 7
    Last Post: 10-03-2012, 01:19 PM
  3. malloc() in function, free() without
    By SashaN in forum C Programming
    Replies: 4
    Last Post: 08-06-2012, 06:29 AM
  4. free function
    By rakeshkool27 in forum C Programming
    Replies: 6
    Last Post: 06-06-2010, 03:29 PM
  5. free function
    By vapanchamukhi in forum C Programming
    Replies: 2
    Last Post: 09-18-2008, 02:48 PM

Tags for this Thread