Thread: assert(tree != NULL) doesnt fail

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    808

    assert(tree != NULL) doesnt fail

    i moved the free(tree) call out of main and put it at the end of my destroy function. then in main added the assert but it doesn't fail. i ran valgrind --leak-check=full ./trunk and it says there is no memory leaks. i know its running on the latest version because of the data its spewing out to the screen

    im just a little confused as to why the assert doesn't fail if the tree has actually been freed

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Maybe you merely called free() but didn't set the pointer to be a null pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    ok thanks is that something i should be doing then?
    coop

  4. #4
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    that doesn't fail either
    Code:
    void destroy(Bin_Tree *tree)
    {
        Bin_Node *root = tree->root;
    
        destroy_tree(root);
        free(tree);
        tree = NULL;
    }
    i tried tree->root = NULL as well

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Um, tree in this context is a local variable. You're just making a copy of the tree pointer to be a null pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    so if it's local how am i freeing the real tree?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Because it's a pointer. The pointer points to memory. A copy of the pointer also points to the same memory. A copy of that copy of the pointer also points to the same memory. So, if you change (or free) the object stored in that memory through the copy of the copy of the pointer, it will appear changed when you access the memory via the copy or the original. But if you set that copy of a copy to be a null pointer, it has absolutely no effect on the copy and the original pointer because it is a copy (of the copy).
    Last edited by laserlight; 06-14-2019 at 05:05 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by cooper1200 View Post
    that doesn't fail either
    Code:
    /* the argument 'tree' is LOCAL to the function. It is a COPY from the
       original pointer!!! */
    void destroy(Bin_Tree *tree)
    {
        Bin_Node *root = tree->root;
    
        destroy_tree(root);
        free(tree);
        tree = NULL;  // this will set the LOCAL 'tree' to NULL!
    }
    What you wanted to do:
    Code:
    void destroy(Bin_Tree **treepp)
    {
        Bin_Node *root = (*treepp)->root;
    
        destroy_tree(root);
        free(*treepp);
        *treepp = NULL;
    }
    Get it?

  9. #9
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    i guess the answer to all this as main creates the variable *tree and then calls create tree it is reasonable for main to set the tree to null or of course implement flp's suggestion and send in &tree to destroy rather than tree.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why does tree in main need to be a pointer with dynamic memory allocation?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Apr 2019
    Posts
    808
    same way i had to create list with dynamic memory
    double linked list
    Last edited by cooper1200; 06-14-2019 at 05:29 AM.

  12. #12
    Registered User
    Join Date
    May 2019
    Posts
    214
    @cooper1200,

    You've just repeated the same lesson we've gone through on the manipulation of Bin_Tree's root inside your AVL code.

    I think you have developed a belief that somehow a variable and the memory location returned by malloc are married into a kind of unified concept, but they're not.

    To demonstrate:

    Code:
    Bin_Tree *t1 = malloc( sizeof( Bin_Tree ) );
    
    Bin_Tree *t2 = t1;
    
    Bin_Tree *t3 = t2;
    All three, t1, t2, and t3 point to the same address given by malloc

    Now

    Code:
    free( t3 );
    t3 = null;
    At this point, t3 is null and the memory is freed.

    However, t1 and t2 still hold their pointer to that memory, even though the memory is freed, and if t1 and t2 use that pointer to see inside Bin_Tree, it will crash.

    Another to drive this home....

    Code:
    Bin_Tree *t1 = malloc( sizeof( Bin_Tree ) );
    
    destroy( t1 );
    
    void destroy( Bin_Tree * t1 )
    {
     free( t1 );
     t1 = NULL;
    }
    No matter what the name of the parameter in destroy, the memory is freed (as in the first example), but t1 is only set to NULL in the function. It is a copy of the pointer, so the caller of destroy still has a pointer to what malloc returned, but it still has been freed in destroy.

    The only way a function can modify the parameter passed to it is with the idiom you've used for AVL tree insertion, like

    Code:
    Bin_Tree *t1 = malloc(.....);
    
    destroy( &t1 ); /// the address of t1 is a pointer to a pointer of Bin_Tree
    
    
    
    void destroy( Bin_Tree ** t1 )
    {
     free( t1 );
     t1 = NULL;
    }

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I asked you why, not "give me another example in which you did this unnecessary thing". So nope, you don't have to do that. Not for list, not for tree.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    May 2019
    Posts
    214
    @cooper1200,

    Actually, @laserlight's question is a point within that question that is slightly more profound.

    Due to the nature of the example code you're writing, you could actually use Bin_Tree on the stack. It is only Bin_Tree's root member that is dynamic.

    Still, it IS dynamic, and something has to manage that, but Bin_Tree could be on the stack and all would work fine (automatic deletion of Bin_Tree), just not the Bin_Tree's root node. That would still be a clear of the tree.

    However, in more "real" code (not an example), where Bin_Tree may mutate into a re-usable library, it would be rare that you could get away with that, and Bin_Tree would have to be dynamic as you're doing that now.

  15. #15
    Registered User
    Join Date
    May 2019
    Posts
    214
    @laserlight, unless I misunderstand @cooper1200 from many threads he's started in AVL trees, I think he's studying to advance the code to a real, usable AVL tree, ultimately, where int may even be replaced with void *, and a pointer to a comparison function would eventually be required, so this tree would balance over hundreds or thousands of entries.

    I am, however, making some assumption about that.

    His larger, main code was already tested with up to 500 nodes, but not yet balanced by AVL

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Assert: When to and when not to.
    By Shamino in forum C++ Programming
    Replies: 22
    Last Post: 01-27-2012, 09:55 AM
  2. fail to count digit of an integer (fail at 9)
    By azsquall in forum C++ Programming
    Replies: 3
    Last Post: 05-02-2008, 09:42 AM
  3. accept(ListenSocket, NULL, NULL); cause program to hang?
    By draggy in forum Networking/Device Communication
    Replies: 11
    Last Post: 06-16-2006, 03:40 PM
  4. Assert
    By Shamino in forum C++ Programming
    Replies: 8
    Last Post: 01-24-2006, 11:02 AM
  5. assert
    By ammar in forum C++ Programming
    Replies: 1
    Last Post: 10-19-2002, 08:17 AM

Tags for this Thread