Document proper usage of BipedalLocomotion::Contacts::ContactList::editContact()
LoreMoretti opened this issue · comments
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.
The problem is that
bipedal-locomotion-framework/src/Contacts/src/ContactList.cpp
Lines 208 to 209 in e341b70
might invalidate existing iterators.
It should be at least documented. It would be even better if we avoid to have this issue at all
What about something as follows:
- Change the
editContact
signature, from
to bool editContact(const_iterator& element, const BipedalLocomotion::Contacts::PlannedContact& newContact);
- Changing the
erase
andinsert
lines from:
bipedal-locomotion-framework/src/Contacts/src/ContactList.cpp
Lines 208 to 209 in e341b70
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
:
This should have the effect of changing the
const_iterator element
(which is invalidated by theerase
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.
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.
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.