CharlyDelta
CharlyDelta

Reputation: 938

Boost shared_ptr in ptr_list

I am new to C++ and quickly began using the boost library, since it offers a lot of functionality I need. Especially the BOOST_FOREACH is very useful to me so I can easily iterate through a boost ptr_list. Eventually I needed to use another library, which uses boosts shared_ptr.

Here is my code:

bool SdfParser::parseDataStructure(sdf::ElementPtr sdfRoot)
{
    /* sdfRoot is the root of a xml-like data structure. The first child is "world" and the childs of "world" are several "model" elements */

    nddlgen::models::Workspace* workspace = new nddlgen::models::Workspace();
    workspace->setName("workspace");

    this->_armModel->setWorkspace(workspace);

    sdf::ElementPtr workspaceElement = sdfRoot->GetElement("world");
    sdf::ElementPtr currentModelElement = workspaceElement->GetElement("model");

    nddlgen::types::ModelList models;

    // The sdf lib only offers a useless data structure for the models, so it is
    // converted into a ModelList here
    while (currentModelElement != nullptr)
    {
        models.push_back(&currentModelElement);

        // Iterate
        currentModelElement = currentModelElement->GetNextElement("model");
    }

    if (!this->instantiateModels(models))
    {
        return false;
    }

    if (!this->calculateDependencies(models))
    {
        return false;
    }

    return true;
}

Explanation:

Problem:

The code shown here compiles without errors or warnings, but I get the following output when I run the compiled program: *** Error in './nddl-generator-cli': double free or corruption (out): 0x00007ffd0ff46460 ***.

What I tried:

I tried to retrieve the sdf::Element from sdf:ElementPtr and changed the other code accordingly, but it would not work. I would get some compiler errors. Anyway, I would not like to ignore the libraries suggested use of sdf::ElementPtr.

Later I tried to remove the & in the argument of the push_back function, but this does not compile, of course, since the push_back function requires a pointer.

Also I dont wan't to go without boost's BOOST_FOREACH, so I also don't want to use any other type of list.

How can it be that boosts ptr_list does not work with boosts shared_ptr? What can I do to use sdf::ElementPtr as well as BOOST_FOREACH?

[Edit] Solution:

See accepted answers, especially comments. The trick was to use std::list instead of boosts ptr_list, since BOOST_FOREACH also accepts those.

Upvotes: 0

Views: 304

Answers (2)

sehe
sehe

Reputation: 392999

Boost Pointer Containers explicitly own their elements. Consequently there cannot be shared ownership.

Just store

  • shared pointers (shared_ptr<T>) in the container (if the container should keep the elements alive)
  • weak pointers (weak_pointer<T>) in the container (if the container should be able to detect stale elements)
  • raw pointers (T*) if you know that elements will always live longer than the container.

Upvotes: 1

Xiaotian Pei
Xiaotian Pei

Reputation: 3260

It's very strange that you already use shared_ptr for currentModelElement, and but put the address of that shared_ptr in ptr_list. You should put shared_ptr in a normal list.

And when you put &currentModelElement in ptr_list, all the element in ptr_list are actually the same. They all point to the address of a local variable which is a shared_ptr, when ptr_list' destructor is called, the same shared_ptr pointer is deleted several times.

Upvotes: 1

Related Questions