rapidjson c++ deallocate Array within Object

4.2k views Asked by At

I'm using the rapidjson C++ library, with this library you can create a JSON object. Currently I'm having some memory issues.

The situation:

In my current setup I’ve created a new object, and added value members and an array member to it. The object is passed by reference to multiple functions and used in the flow of my program.

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());
    }
}

I’m using the same object in a loop, and thus erasing the members of the object before I’m adding the members again. I’m using the EraseMember function for this. However I’ve noticed that this function isn’t releasing the memory of the array member, and thus leaks memory.

How can I make rapidjson to release the complete object with all it members?

1

There are 1 answers

1
Milo Yip On

The current implementation of RapidJSON uses a std::vector like data structure to store members of object.

In your case, removing all members and adding members again, does not make leak per se.

However, since some values of members are array, when they are destructed, it will call the allocator to free the memory. But if you are using the default allocator rapidjson::MemoryPoolAllocator, it does not free the memory. And this will increase the memory usage for each iteration.

If you need to frequently allocate/deallocate values, use rapidjson::CrtAllocator instead.

Alternatively, it can be optimised if those values are only used within the block, you may also create a local 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
}

This "advanced" usage can even prevent heap allocation if the buffer is sufficient in the loop.