Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document proper usage of BipedalLocomotion::Contacts::ContactList::editContact() #847

Open
LoreMoretti opened this issue May 10, 2024 · 5 comments

Comments

@LoreMoretti
Copy link
Contributor

The function BipedalLocomotion::Contacts::ContactList::editContact might cause segmentation fault if used within loops, such as for loops.

For example the following pseudo-code:

       newContactList =  myContactList;

        for (auto it = myContactList.begin(); it != myContactList.end(); it++)
        {
            BipedalLocomotion::Contacts::PlannedContact newContact{};
            
            // ===== do something meaningfull with newContact      

            newContactList.editContact(it, newContact);
        }

@S-Dafarra pointed out the it could be due to these lines.

It should be documented that this function should not be used within loops.

@S-Dafarra
Copy link
Member

The problem is that

m_contacts.erase(element);
m_contacts.insert(nextElement, newContact);

might invalidate existing iterators.

It should be at least documented. It would be even better if we avoid to have this issue at all

@LoreMoretti
Copy link
Contributor Author

What about something as follows:

  1. Change the editContact signature, from

bool editContact(const_iterator element,
const BipedalLocomotion::Contacts::PlannedContact& newContact);

to bool editContact(const_iterator& element, const BipedalLocomotion::Contacts::PlannedContact& newContact);

  1. Changing the erase and insert lines from:
    m_contacts.erase(element);
    m_contacts.insert(nextElement, newContact);

to

    element = m_contacts.erase(element);
    element = m_contacts.insert(element, newContact);

This should have the effect of changing the const_iterator element (which is invalidated by the erase function) to a new valid one, which points at the inserted element.

Could it work?

If it works, then we should change also the way editContact is called within forceSampleTime:

if (!this->editContact(std::next(this->begin(), i), newContact))

@S-Dafarra
Copy link
Member

This should have the effect of changing the const_iterator element (which is invalidated by the erase function) to a new valid one, which points at the inserted element.

Could it work?

Unfortunately, I don't think so. The erase can invalidate all existing iterators, not just the one we are passing.

@LoreMoretti
Copy link
Contributor Author

Unfortunately, I don't think so. The erase can invalidate all existing iterators, not just the one we are passing.

I see your point, which in fact is also reported in the c++ documentation.

Though, in the erase documentation, I see the following example:

std::vector<int> c{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

// Erase all even numbers
    for (std::vector<int>::iterator it = c.begin(); it != c.end();)
    {
        if (*it % 2 == 0)
            it = c.erase(it);
        else
            ++it;
    }

where iterators get erased within a for loop, which cycles on the iterators themselves.

@S-Dafarra
Copy link
Member

I see. In any case, this would fix the issue with the iterator to the item that has been edited. The problem is if you have other iterators around. Those could also become invalid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants