Я написал приложение с использованием wxWidgets, которое использует wxList. У меня есть случайные судороги (segfault) в деструкторах, которые собирают данные списка. Я не смог найти определенный способ удаления элементов из списка (Erase() VS DeleteNode()). Даже итерация над элементами имеет два варианта (list-> GetFirst() VS list-> begin()).Каков правильный способ обработки связанных списков в wxWidgets?
Ниже приведен тестовый класс, показывающий подход, который я использую в своем приложении. Тест проходит отлично, без сбоев. Кажется, что некоторые указатели используются после того, как они освобождены, но я не могу сказать это, посмотрев на код. Я полагаю, что я делаю что-то неправильно в вызовах Erase() и DeleteContents().
P.S: в приложении список содержит около 15 тысяч наименований, а не только 9 в тесте.
#include <wx/list.h>
#include <wx/log.h>
class TestItem
{
public:
TestItem(int _x, int _y) { x = _x; y = _y; }
int x;
int y;
};
WX_DECLARE_LIST(TestItem, TestList);
#include <wx/listimpl.cpp>
WX_DEFINE_LIST(TestList);
class Test {
public:
TestList *list;
Test() {
list = new TestList;
}
~Test() {
Clean();
delete list;
}
void CreateAndAddToList(int x, int y) {
TestItem *item = new TestItem(x, y);
list->Append(item);
}
void PrintAll() {
wxLogMessage(wxT("List size: %d"), list->GetCount());
wxTestListNode *node = list->GetFirst();
while (node) {
TestItem *item = node->GetData();
wxLogMessage(wxT("Item: %d, %d"), item->x, item->y);
node = node->GetNext();
}
}
void DeleteAllX(int x) {
wxTestListNode *node = list->GetFirst();
while (node) {
TestItem *item = node->GetData();
if (item->x != x) {
node = node->GetNext();
continue;
}
wxTestListNode *toDelete = node;
node = node->GetNext();
wxLogMessage(wxT("Deleting item: %d, %d"), item->x, item->y);
list->Erase(toDelete);
delete item;
}
}
void Clean() {
list->DeleteContents(true);
list->Clear();
}
static void DoAllTests() {
Test *t = new Test;
t->CreateAndAddToList(1, 1);
t->CreateAndAddToList(1, 2);
t->CreateAndAddToList(1, 3);
t->CreateAndAddToList(2, 1);
t->CreateAndAddToList(2, 2);
t->CreateAndAddToList(2, 3);
t->CreateAndAddToList(3, 1);
t->CreateAndAddToList(3, 2);
t->CreateAndAddToList(3, 3);
t->PrintAll();
t->DeleteAllX(2);
t->PrintAll();
t->Clean();
t->PrintAll();
delete t;
}
};
Вы можете избежать головных болей и проблем и использовать 'std :: list'. Уже закодированы и протестированы миллионами пользователей. –
В документах я не заметил, что wxList устарел. В любом случае, новый API практически идентичен std :: list. Я изменил свое приложение, чтобы использовать std :: list, некоторые из ошибок, похоже, исчезли. По крайней мере, сейчас у меня есть гораздо больше документации о бэкэнде списка. – streeto