Thread: free double pointer

  1. #1
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463

    free double pointer

    Hi,
    This maybe a stupid question, but here goes. I just want to see how free and NULL would work with a pointer to pointer, so I have this code:

    Code:
    void free_array(int ** ptptArr, int m)
    {
      for ( int i = m ; i >= 0; i--)
        {
          free(ptptArr[i]);
          ptptArr[i] = 0;
          printf("set ptptArr[%2d] = NULL.\n",i);
        }
      putchar('\n');
      free(ptptArr);
    
      ptptArr = 0;
      if(ptptArr == NULL) printf("set **ptptArr to NULL.\n");
    }
    Then, in main, I have:
    Code:
      // ut is type int **
      free_array(ut,n);
    
      printf("After free.\n\n");
      
      for(int k = 0; k < n; k++)
        {
          ut[k] == 0 ? printf("ut[%d] = Null\n",k) : printf("ut[%d] != Null\n",k);
        }
    
        
      ut == NULL ? printf("**ut = NULL.\n") : printf("**ut != Null.\n");
        
      
      for (int i=0;i<n;i++)
        {
          printf("%d ",i);
          for(int j= 0;j<n;j++)
    	printf("%2d     ", ut[i][j]);
          putchar('\n');
        }
    So i thought it's supposed to set all the pointer "ut[k]" to null, and "ut" to null as well. After compiled and run, I get:
    Code:
    After free.
    
    ut[0] != Null
    ut[1] = Null
    ut[2] = Null
    ut[3] = Null
    ut[4] = Null
    ut[5] = Null
    ut[6] = Null
    ut[7] = Null
    ut[8] = Null
    ut[9] = Null
    **ut != Null.
    0  0     49     135696480      1      2      3      4      5      6      7     
    Segmentation fault
    .
    I thought that "ut" is set to null, but it's not. Why does that function not work?

    However, if i don't use the function to free, and do all the free-up and setting to NULL in main:
    Code:
    for ( int i = n ; i >= 0; i--)
        {
          free(ut[i]);
          ut[i] = 0;
          printf("set ptptArr[%2d] = NULL.\n",i);
        }
      ut = 0;
      printf("After free.\n\n");
      
    
      ut == NULL ? printf("**ut = NULL.\n") : printf("**ut != Null.\n");
        
      for(int k = 0; k < n; k++)
        {
          ut[k] == 0 ? printf("ut[%d] = Null\n",k) : printf("ut[%d] != Null\n",k);
        }
    
        
     
      
      for (int i=0;i<n;i++)
        {
          printf("%d ",i);
          for(int j= 0;j<n;j++)
    	printf("%2d     ", ut[i][j]);
          putchar('\n');
        }
    Then, "ut" is set to NULL, and I can't access it anymore:
    Code:
    **ut = NULL.
    Segmentation fault
    Last edited by nimitzhunter; 12-17-2010 at 04:05 PM.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Code:
    ptptArr = 0;
    Just because a variable has a star in front of it doesn't mean everything you know about functions go out the window. You cannot change the value of a passed-in parameter to a function in a way visible to the caller, no matter how hard you try.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    free() only tells the C runtime that you are promising not to use the memory any more. It does not require the C runtime to make sure you cannot access it. If you do so, you invoke undefined behaviour - which means that anything is allowed to happen, whether it makes sense to you or not.

    When something is passed by value to a function, the change in the function is not visible to the caller.
    Code:
    #include <stdio.h>
    void func(int x)
    {
         x = 3;
    }
    
    int main()
    {
        x = 2;
        func(x);
        printf("%d\n", x);   /* will print 2 */
    }
    The same happens with pointers.
    Code:
    void some_func(int **ptptArr)
    {
        ptptArr = NULL;    /*   this change is also invisible to the caller, as the pointer itself is passed by value */
    }
    The problem with your code is that, after calling free_array(), the value of ut in main() has not changed, but what it points to is no longer valid. The onus is on main() - or, more accurately, you as the person writing main() - to not dereference ut after that (i.e. don't access any ut[i]). Nothing stops you dereferencing ut. But, if you do, the results are undefined (eg a program crash, values you don't expect).
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    Is this the correct way to free "ut" and set "ut" to null as well in the function by using a pointer to "int**". Would this make the parameter "int ***"?

    Code:
    void free_array(int *** ptptArr, int m)
    {
      for ( int i = m ; i >= 0; i--)
        {
          free( (*ptptArr)[i] );
          ptptArr[i] = 0;
          printf("set ptptArr[%2d] = NULL.\n",i);
        }
      putchar('\n');
      free(*ptptArr);
    
      *ptptArr = 0;
     
    }
    then in main call:
    Code:
    free_array(&ut,n);
    Oh, yeah, and is it redundant to set the pointer to NULL after free? I googled that, and some people are for it, and some people are against it.
    Last edited by nimitzhunter; 12-17-2010 at 05:52 PM.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  5. #5
    Registered User hellork's Avatar
    Join Date
    Nov 2010
    Posts
    39
    Personally, I do not bother to set them on projects like these preferring to use scope rules, but in a larger program, especially one of those projects that is full of hacks and uses globals all over it could become difficult to remember which buffers are available for writing. Some of those projects might be candidates for reference counting or garbage collection.

    An exhaustive popular sentiment on dangling pointers:
    Dangling pointer - Wikipedia, the free encyclopedia

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by nimitzhunter View Post
    Is this the correct way to free "ut" and set "ut" to null as well in the function by using a pointer to "int**". Would this make the parameter "int ***"?
    If you want to do it that way, it is one valid way.

    Note that the line "ptptArr[i] = 0;" in your code is incorrect. It should either be "(*ptptArr)[i] = 0;" or, since you are freeing *ptptArr anyway, it can be removed.

    Quote Originally Posted by nimitzhunter View Post
    Oh, yeah, and is it redundant to set the pointer to NULL after free? I googled that, and some people are for it, and some people are against it.
    I'm with hellork on preferring scope rules: if the pointer itself ceases to exist immediately after being free()'d then there is no point in setting it to NULL first.

    There is actually no substitute for careful analysis of what your code does, so you know when an object will cease to exist. The "set pointer to NULL after freeing" actually encourages laziness - too many people use it to (partially) compensate for sloppy design.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    -bleh-
    Join Date
    Aug 2010
    Location
    somewhere in this universe
    Posts
    463
    Thanks alot guys for the valuable inputs.
    "All that we see or seem
    Is but a dream within a dream." - Poe

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Is this the correct way to free "ut" and set "ut" to null as well
    Only that you should have started at m-1 in your for loop.

    But then again, why ARE you running the loop backwards anyway?
    You only need to free the array elements before freeing the array. So long as you do that, all should be fine.

    malloc would be useless if you HAD to precisely reverse the order whenever you called free.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. functions and passing data
    By redmondtab in forum C Programming
    Replies: 41
    Last Post: 09-21-2006, 12:04 PM
  2. newbie needs help with code
    By compudude86 in forum C Programming
    Replies: 6
    Last Post: 07-23-2006, 08:54 PM
  3. towers of hanoi problem
    By aik_21 in forum C Programming
    Replies: 1
    Last Post: 10-02-2004, 01:34 PM
  4. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM
  5. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM