Daniel Wagner wrote:
> Daniel Wagner wrote:
>>> I think I have found the source of the segfaults during closedown. In
>>> PortManager::~PortManager a vector iterator is used to loop through all
>>> registered ports so they can be deleted. It seems that following the delete
>>> operation, *it points not to the deleted port but to the one which followed
>>> it in the list.
>> That is not normal. The iterator should not be changed at all. Maybe we have to
>> check what 'delete *it' does on the memory. Maybe some sort of memory corruption?
>
> Following is happening:
>
> ~PortManager() is called
> - an iterator is created over m_Ports
> - delete *it
>
> ~Port() is called
> - call m_manager.unregisterPort(this)
>
> PortManager::unregister is called
> - create a interator over m_Ports
> - call erase(it)
>
> So the problem is that m_Ports is changed in the 'inner' function while a
> iterator is hold in ~PortManager. That is clearly invalid code sequence.
I plead guilty... I somewhere introduced that ports register/unregister
themselves to the manager on creation/destruction. It seemed to be a
cleaner method, since I could use a reference instead of a pointer,
meaning that I could eliminate all the null pointer checks. But since it
used to be pointer based (and a mess) I introduced this.
Should be fixed when we use a while(items) {delete pop()} loop.
Greets,
Pieter

Daniel Wagner wrote:
>> I think I have found the source of the segfaults during closedown. In
>> PortManager::~PortManager a vector iterator is used to loop through all
>> registered ports so they can be deleted. It seems that following the delete
>> operation, *it points not to the deleted port but to the one which followed
>> it in the list.
>
> That is not normal. The iterator should not be changed at all. Maybe we have to
> check what 'delete *it' does on the memory. Maybe some sort of memory corruption?
Following is happening:
~PortManager() is called
- an iterator is created over m_Ports
- delete *it
~Port() is called
- call m_manager.unregisterPort(this)
PortManager::unregister is called
- create a interator over m_Ports
- call erase(it)
So the problem is that m_Ports is changed in the 'inner' function while a
iterator is hold in ~PortManager. That is clearly invalid code sequence.
daniel

> I think I have found the source of the segfaults during closedown. In
> PortManager::~PortManager a vector iterator is used to loop through all
> registered ports so they can be deleted. It seems that following the delete
> operation, *it points not to the deleted port but to the one which followed
> it in the list.
That is not normal. The iterator should not be changed at all. Maybe we have to
check what 'delete *it' does on the memory. Maybe some sort of memory corruption?
> However,
> at the back of my mind I'm wondering whether all this is just relying on
> undocumented iterator behaviour. Is it actually valid to delete vector
> members while an iterator is active over the vector and is the observed
> behaviour something we can rely on across c++ compiler versions?
The cleanup strategy we are using is ok. The only thing you have to be
careful is not to destroy or change the iterators in the loop. When dereferencing the
iterator we get our pointer back we stored in the vector. We can do what we
want with this pointer. The iterator doesn't care.
> This is a question we ought to answer because a quick search for "delete
> *it" showed that this iterator/delete construct is used in a fair number of
> places. I would say that like in the PortManager case the delete loop is
> probably only deleting every second vector element. While this may not
> cause any major visible issues given that the code is generally only
> associated with closedown, it is something we should fix.
Could you test following program?
#include <cstdio>
#include <vector>
using namespace std;
class Foo {
public:
Foo() {}
virtual ~Foo() {}
};
typedef vector<Foo *> FooVector;
typedef vector<Foo *>::iterator FooVectorIterator;
int main (int argc, char *argv[])
{
const int nr = 3;
FooVector foos;
for (int i = 0; i < nr; i++) {
Foo *foo = new Foo;
if (foo) {
printf("foo %d: %p\n", i, foo);
foos.push_back(foo);
}
}
for (FooVectorIterator it = foos.begin(); it != foos.end(); ++it) {
printf("before delete: *it %p\n", *it);
delete *it;
printf("after delete: *it %p\n", *it);
}
return 0;
}
I get following output on my machine:
foo 0: 0x804b008
foo 1: 0x804b028
foo 2: 0x804b018
before delete: *it 0x804b008
after delete: *it 0x804b008
before delete: *it 0x804b028
after delete: *it 0x804b028
before delete: *it 0x804b018
after delete: *it 0x804b018
I try to figure out what ~Port() is doing. It seems that this part of the code
is not used for my bebob devices.
cheers,
daniel

Community

Help

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

CountryState

JavaScript is required for this form.

I agree to receive quotes, newsletters and other information from sourceforge.net and its partners regarding IT services and products. I understand that I can withdraw my consent at any time. Please refer to our Privacy Policy or Contact Us for more details