Rapidjson C++ освобождает массив внутри объекта

Я использую библиотеку C++rapidjson, с помощью которой вы можете создать объект JSON. В настоящее время у меня есть некоторые проблемы с памятью.

Ситуация:

В моей текущей настройке я создал новый объект и добавил к нему элементы-значения и элемент массива. Объект передается по ссылке нескольким функциям и используется в потоке моей программы.

rapidjson::Value data;
data.SetObject();

while(...)
{
    // --------------------------
    // Add coordinates to object

    JSON::AllocatorType& allocator = data.GetAllocator();

    JSONValue region;
    region.SetArray();
    region.PushBack(rectangle.m_x1, allocator);
    region.PushBack(rectangle.m_y1, allocator);
    region.PushBack(rectangle.m_x2, allocator);
    region.PushBack(rectangle.m_y2, allocator);

    data.AddMember("regionCoordinates", region, allocator);

    // --------------------------
    // Add number of changes

    data.AddMember("numberOfChanges", numberOfChanges, allocator);

    ... call function and pass data
    ... call function2 and pass data

    if(data.MemberBegin() != data.MemberEnd())
    {
        data.EraseMember(data.MemberBegin(), data.MemberEnd());
    }
}

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

Как я могу заставить Rapidjson выпустить полный объект со всеми его членами?


person Cédric Verstraeten    schedule 23.06.2015    source источник


Ответы (1)


Текущая реализация RapidJSON использует структуру данных, подобную std::vector, для хранения членов объекта.

В вашем случае удаление всех членов и повторное добавление членов не приводит к утечке как таковой.

Однако, поскольку некоторые значения членов являются массивами, при их уничтожении будет вызываться распределитель для освобождения памяти. Но если вы используете распределитель по умолчанию rapidjson::MemoryPoolAllocator, он не освобождает память. И это увеличит использование памяти для каждой итерации.

Если вам нужно часто выделять/освобождать значения, используйте вместо этого rapidjson::CrtAllocator.

Кроме того, его можно оптимизировать, если эти значения используются только внутри блока, вы также можете создать локальный Allocator:

char buffer[1024];
Value::Allocator localAllocator(buffer, sizeof(buffer));
while (...)
{
   Value region;
   region.SetArray();
   region.PushBack(rectangle.m_x1, localAllocator);

   // ...
   localAllocator.Clear(); // Only available for MemoryPoolAllocator
}

Это «расширенное» использование может даже предотвратить выделение кучи, если в цикле достаточно buffer.

person Milo Yip    schedule 05.08.2015
comment
У меня такая же проблема. Это ужасно и приводит к сбою онлайн-производства. Я надеюсь, что это может быть задокументировано лучше. :-) - person leeyiw; 21.09.2018