I needed to do the same, and thought I'd note what from reading the allocator code seems to be an alternative:
While I again create a char buffer[2048], I do not create and keep an allocator alongside it.
Rather, I create and delete an allocator anew when needed, while re-using the memory block. From reading the code of the allocator I see no Malloc so that should all be on the stack, no?
Edit - code example:
class MyClass
{
public:
myClass() :
_json_log_string_buffer(&_json_string_buffer_allocator,
_json_buffer_size) {}
(...)
private:
static constexpr int _json_buffer_size {4096};
char _json_logger_buffer[_json_buffer_size];
rapidjson::CrtAllocator _json_string_buffer_allocator;
rapidjson::StringBuffer _json_log_string_buffer;
};
MyClass::log_to_json()
{
rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>
json_logger_allocator {_json_logger_buffer,
sizeof(_json_logger_buffer)};
rapidjson::Document json_doc(&json_logger_allocator);
auto& allocator = json_doc.GetAllocator();
json_doc.SetObject();
// using it:
json_doc.AddMember("id", id(), allocator);
json_doc.AddMember("KEY", "VALUE",
allocator);
(...)
// Here, monitoring the size of allocator, it never goes
// beyond the 4096 on repeat invocations.
// If I had it as a member, only creating once, it would grow.
std::cout << "JSON allocator size: " << allocator.Size() <<
", capacity: " << allocator.Capacity() << std::endl;
// Bonus point: I'm also using a rapidjson::StringBuffer.
// From a first read it doesn't seem to re-allocate.
// It doesn't use a MemoryPoolAllocator so I cannot do the
// same for it as I did for rapidjson::Document.
_json_log_string_buffer.Clear();
rapidjson::Writer<rapidjson::StringBuffer>
writer(_json_log_string_buffer);
json_doc.Accept(writer);
auto as_string = _json_log_string_buffer.GetString();
// Using string with logger...
}