C ++ map.erase () вызывает нежелательную балансировку - PullRequest
0 голосов
/ 14 января 2012

У меня есть map<uint, Order*> orders, где Order - это определенный класс с соответствующими полями, такими как id, время, цена и объем. У меня также есть ветка, которая прослушивает добавления и удаления входящих заказов для карты, определенной ниже.

void System::OrderDeleted_Thread(unsigned int order_id)
{
    if(orders.find(order_id) != orders.end())
    {
            Order* order = orders[order_id];
            orders.erase(order_id);
            delete order;
    }
}

Моя проблема очень похожа на эту:

Ошибка сегментации в функции std std :: _ Rb_tree_rebalance_for_erase ()

Мой вопрос: как я могу выполнить итерацию по моей карте заказов, если программа не выдаст мне ошибку, когда придет время перебалансировать дерево? Как и в решении, указанном в ссылке, я вынул метод .erase (uint) и заставил его работать. К сожалению, я не могу хранить карту из нескольких десятков тысяч ключей.

Заранее спасибо!

Ответы [ 3 ]

4 голосов
/ 14 января 2012

У меня также есть нить, которая прослушивает добавления и удаления входящих заказов для карты, определенной ниже.

Вам необходимо синхронизировать доступ к карте.Контейнеры STL не являются поточно-ориентированными с несколькими записывающими устройствами (а стирание элементов выполняет запись в контейнер) без какой-либо внешней синхронизации.

1 голос
/ 14 января 2012

Поставьте в очередь свои добавления и удаления в отдельной структуре данных, а затем обработайте их в безопасное время, когда вы гарантированно не будете выполнять итерации по карте.Это безопасное время может быть после того, как вы приобрели мьютекс, который защищает карту, или каким-либо другим способом, в зависимости от вашей программы.

0 голосов
/ 14 января 2012

Помимо проблем с синхронизацией, это дорогостоящий способ написания цикла. Вместо этого попробуйте это:

std::map<uint, Order*>::iterator it;
Order * p = NULL;

{ // enter critical section
    if ((it = orders.find(id)) != orders.end())
    {
        p = it->second;
        orders.erase(it);
    }
} // leave critical section

delete p;
...