Defining the behaviour of the delete system

Help
2008-07-09
2013-04-24
  • Danny Staple
    Danny Staple
    2008-07-09

    I was a little confused about how this deleted items - specifically the first in the hash. I therefore modified the users example to print pointers to the users list, and a new user when creating a user, and the same before deleting a user, and after.

    What I found is that the pointer passed into HASH_DEL for the hash list is actually changed to point to the next item, and if the last remaining item is deleted, this pointer is set to NULL. This should help out anyone looking for that info. It is perfectly safe to delete the first item - but make sure you wrap uthash, as a dangling copied reference to the start of it will be invalid if stuff is deleted from it.

    The users example leaks memory BTW - it does not actually free any of the users structures.

     
    • Troy Hanson
      Troy Hanson
      2008-07-09

      You're right on all counts. The hash deletion, when applied to the first element, does indeed change the head pointer. When the final item is deleted the head pointer changes to NULL. A program that uses uthash should not keep other copies of the head pointer because HASH_DEL can change the head.

      Good point about the leak in the example program. I'll see if I can fix that in my next release, along with adding this explanation of the delete behavior.

       
      • Danny Staple
        Danny Staple
        2008-07-12

        Do you think you could do an example with a "delete all" - hash clearing demonstration. I did figure one out, but I got it wrong at first, given that if you delete as you iterate, the hh struct will have its next pointer reset.
        I think the simplest way may be something like:

        while(users)
        {
          user_struct * current_user = users;
          HASH_DEL(users);
          free(current_user);
        }

        Given that users is the top of the list, and user_struct is the associated structure, this would delete all the items, free the actual associated data, and NULL the list head, so it could be used again. The use case is when the hash is used to cache results, and then it is cleared for the next operation.

         
        • Troy Hanson
          Troy Hanson
          2008-07-14

          Yes definitely that's something I want to add to the revised User Guide. I really like your code fragment actually, its a bit cleaner looking than the way I usually do it. Which is,

          user_struct *next_user; 
          for(user=users; user; user=next_user) {
          next_user = user->hh.next;
          HASH_DEL(users,user);
          free(user);
          }

          Like I said, I think yours is a little clearer, and would be the right approach to demonstrate in the user guide.

          I'm close to having a uthash release ready, so this is good timing.

           
    • Danny Staple
      Danny Staple
      2008-07-12

      Sourceforge really need to add two things.. A preview button for messages, and support for code style blocks which keep indenting.

       
    • Troy Hanson
      Troy Hanson
      2008-07-18

      This is the example of delete-all that I cooked up for inclusion in the User Guide.

      void delete_all() {
        struct my_struct *current_user;

        while(users) {
          current_user = users;          /* grab pointer to first item */
          HASH_DEL(users,current_user);  /* delete it (users advances to next) */
          free(current_user);            /* free it */
        }
      }