I am using Rapidjson and have noticed that when I turn on optimization in g++ (-O1/-O2/-O3) I am getting a segmentation fault. I think I have tracked it down to the GenericValue& AddMember() function within rapidjson.
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString());
Object& o = data_.o;
if (o.size >= o.capacity) {
if (o.capacity == 0) {
o.capacity = kDefaultObjectCapacity;
o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
}
else {
SizeType oldCapacity = o.capacity;
o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
}
}
o.members[o.size].name.RawAssign(name);
o.members[o.size].value.RawAssign(value);
o.size++;
return *this;
}
When debugging, I can see that kDefaultObjectCapacity ( is being optimized out (this is a static const SizeType kDefaultObjectCapacity = 16)
Therefore the line "o.capacity = kDefaultObjectCapacity;" is not being executed, and the malloc is mallocing 0 bytes then trying to cast it.
Why is this static const being removed?
I have tried making Object& o both volatile and static, neither worked. Any ideas?
Thanks Will
EDIT: I can't easily run the tests as it's on an embedded platform, rapidjson is built using buildroot at the moment. I tried the unit tests but couldn't get them going on the target.
I can have a look at providing the assembly, but it's part of a big application so it might be difficult finding the right bit.
For info, this is the method that calls the rapidjson code and this is where the problem seems to be:
int16_t FrontEndJSONHandlers::get_run_cfg_packer(JSONEngine& json_engine, char *message, int32_t *length)
{
Document doc;
// Need to pack an empty request to get the data
doc.SetObject();
doc.AddMember(JSONRPC_MEMBER, JSONRPC_VERSION, doc.GetAllocator());
doc.AddMember(METHOD_MEMBER, JSON_RPC_METH_GET_RUN_CFG, doc.GetAllocator());
doc.AddMember(ID_MEMBER, json_engine.GetNextMessageID(), doc.GetAllocator());
// Format the message
json_engine.FormatMessageAndRegisterResponseHandler(&doc, &message, &length, get_run_cfg_handler);
return 0;
}
If I make Document doc static, it doesn't seg fault - not sure whether this is the best way around it though?