std :: map неправильная ошибка размещения

У меня проблема с std :: map. По неизвестным причинам иногда вставки в карту приводят к исключению «неправильное размещение».

Ниже приведена функция, которую я использую для вставки в карту.

BOOL Add2WaitList(Object<LPVOID> *newObj)
{
try
{
_set_se_translator( trans_func );
m_syncWQ.Lock();
if (m_waitingQueue.count(newObj->uid)>0)
{
m_syncWQ.Unlock();
return FALSE;
}
m_waitingQueue[newObj->uid] = *newObj; <-- failing here
m_syncWQ.Unlock();
return TRUE;
}
catch(std::exception &ex){
...
}
catch(SE_Exception &e){
...
}
catch(...){
...
}
}

Может кто-нибудь сказать мне, как это решить?

ПРИМЕЧАНИЕ: я не могу определить шаги, чтобы воспроизвести его.

THX заранее!

Добавление деталей об объекте & карта:

template <typename T>
struct Object{
public:
void Kill()
{
if (response!=NULL)
delete response;
if (object!=NULL)
delete object;
}

enum objType;
std::string uid;
enum status;
double p;
enum execType;
T object;
LPVOID response;
};

std::map<std::string,Object<LPVOID>> m_waitingQueue;

4

Решение

Очевидно, что операция std :: map вызывает проблему

m_waitingQueue[newObj->uid] = *newObj;

На самом деле это операция вставки карты, которая могла бы выделить память за сценой: Как распределяется карта STL? Стек или куча?.Одна из возможных причин — выделение памяти для исключения неправильного размещения: Недопустимые исключения размещения в C ++.

Но этот код сам по себе не приводит к объяснению того, что происходит за кулисами. Я думаю, что требуется больше информации, связанной с m_waitingQueue, поскольку переменная является глобальной, что может быть сделано вне этой функции.

2

Другие решения

исключение std::bad_alloc средства «operator new не удалось «. Так что либо operator new вызывается operator* на newObj (о котором мы ничего не знаем) или оператором вставки карты (что более вероятно).

В частности, когда вы звоните operator[] на карте с некоторым параметром k

Если k не соответствует ключу какого-либо элемента в контейнере,
функция вставляет новый элемент с этим ключом и возвращает ссылку
к его сопоставленной стоимости. Обратите внимание, что это всегда увеличивает контейнер
размер на единицу, даже если элементу не назначено сопоставленное значение (
элемент создается с использованием конструктора по умолчанию).

(как задокументировано Вот).

Map::operator[] предоставляет надежную гарантию на отказ:

Strong guarantee: if an exception is thrown, there are no changes in the container.

но не гарантирует, что исключение не будет сгенерировано (т. е. оно не гарантирует отсутствие броска).

Причина для operator new выбрасывание исключения может иметь различную природу. Тем не менее, все сводится к:

throws bad_alloc if it fails to allocate storage.

Тем не менее, как JamesKanze предлагает в комментариях:

Другая возможная причина для std :: bad_alloc — неопределенное поведение. Если
например, он испортил арену свободного пространства. И реально,
если он действительно исчерпывает память, выделение, где это не удается
будет меняться. Если это систематически здесь, я бы заподозрил проблему в
конструктор копирования Object, больше всего на свете.

означающий, что operator new не удается выделить память из-за некоторой ошибки в других частях программы. Вы можете отлаживать против его нулевого предположения (как назвал бы это статистик) путем выделения (очень) большого куска данных прямо перед вызовом operator[], Если фиктивное распределение не завершится неудачно, вы можете с уверенностью сказать, что в конструкторе копирования есть ошибка.

2

возможно Add2WaitList(Object<LPVOID>) просто звонят миллионы раз, пока у тебя не кончится память.

В этом случае причина будет лежать в другом месте кода — например, в форме бесконечного цикла или регрессии. Другой возможной причиной будет, если ваш Objectпо неосторожности все становятся разными uids. Это может произойти, когда uid например, получается из неинициализированного числа.

0

operator new() функция не может найти запрошенный
объем памяти. Эта функция может быть вызвана из new выражение или
непосредственно в распределителе std::map,

Вы не даете никакой информации относительно контекста.
реальный вопрос: всегда ли это терпит неудачу в этой конкретной точке.
Если у вас действительно не хватает памяти (например, из-за
утечка памяти), можно было бы ожидать, что он ударит другие распределения как
Что ж. Другие возможности в том, что вы портите свободный
космическая арена непосредственно перед вызовом этой функции, или что есть
проблема с конструктором копирования Object<LPVOID> который
заставляет его запрашивать неограниченную память, или который портит
Арена свободного пространства, так что следующее распределение не удается. Вы
скопировать этот объект в другом месте? Тот факт, что вы проходите мимо
указатель подсказывает, может быть, нет, в этом случае это будет
место, где вы увидите проблему.

РЕДАКТИРОВАТЬ:

Поскольку вы разместили код для Object: где делать Object
вы используете оригинал? И на что обычно указывают указатели,
и если он распределяется динамически, как управляется удаление?

Так как Object имеет нет определяемые пользователем конструкторы, что означает
что будут случаи, когда указатели содержат случайный мусор.
И удаление случайных указателей является очень хорошим способом повредить
свободное пространство арены.

Также: я замечаю, что у вас есть то, что выглядит как синхронизация
примитивы (Lock() а также Unlock()). Где еще
m_waitingQueue используемый? Если m_waitingQueue можно получить доступ из
другой поток, все доступы к m_waitingQueue должно быть
синхронизируется, используя тот же объект синхронизации
(m_syncWQ). Попытка изменить m_waitingQueue в другой
нить в то время как вы изменяете его здесь также может привести к
неопределенное поведение (где-то объект очереди пишет
где это не должно).

0