Sunday, June 4, 2017

Boost Intrusive container must be clear before exits

A few weeks ago when I was working on a problem involving linked list, I was stuck in an interesting test case on Boost Intrusive. The error I'm getting is coming from the comment of a source code as seen below:
void destructor_impl(Hook &hook, detail::link_dispatch<safe_link>)
{  //If this assertion raises, you might have destroyed an object
   //while it was still inserted in a container that is alive.
   //If so, remove the object from the container before destroying it.
   (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked());
I was in debug mode, and the program was stopped right there. At first I had overlooked into this important piece, but then later only I got to realize that the comment is giving some clue over there. The comment has clearly stated that I must have the container to be clear before destroying it. So what I did in my class was I extend the list_base_hook:
class FileNode : public list_base_hook<> {
    string name;
    char type;

    FileNode() {}

    void setName(string name) { this->name = name; }
    void setType(char type) { this->type= type; }

typedef boost::intrusive::list<FileNode> FileNodeList;
And this is my test case that causes the error:
    FileNodeList fnl;

    FileNode fn1; = "path_A";

    assert(fn1.is_linked() == false);

    FileNode fn2; = "fileA";


    fnl.clear(); // error will be thrown if this code is removed!
Do take note the above class FileNode does not take any template argument. There is another version using auto_unlink as template argument, just like below:
class FileNode : public list_base_hook<link_mode<auto_unlink> > { 
typedef boost::intrusive::list<FileNode, constant_time_size<false> > FileNodeList;
This feature does not require me to clear the container when the container's destructor is invoked, which happened when the function is exited.