Rapidjson: how to use the same document's memory allocator for parsing multiple times

Created on 16 Aug 2017  路  3Comments  路  Source: Tencent/rapidjson

Hey guys, i'm new to rapidjson library, and i've read rapidjson's documentations carefully.
but still, I have a problem when using rapidjson.
the following is the demonstration code which cause problem.

#include <iostream>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include <vector>

using namespace std;
using namespace rapidjson;

// just for debug
string rapidjsonValueToString(const Value& value) {
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    value.Accept(writer);
    string str(buffer.GetString(), buffer.GetLength());
    return str;
}

// parse
Document parse(const string& str, MemoryPoolAllocator<>& ma) {
    Document doc(&ma);
    doc.Parse(str.c_str(), str.size());
    return doc;
}

int main() {
    string string1("{\"k1\":\"v1\"}");
    string string2("{\"k2\":\"v2\"}");
    string string3("{\"k3\":\"v3\"}");
    vector<string> vec{string1, string2, string3};

    Document doc;
    for (const auto& str : vec) {
        doc = parse(str, doc.GetAllocator());  // here will cause SIGSEGV error in the second loop
        std::cerr << "doc : " << rapidjsonValueToString(doc) << std::endl;
    }
    std::cerr << "doc : " << rapidjsonValueToString(doc) << std::endl;

    return 0;
}

My problems are:

  1. From rapidjson's documentation, for saving memory reallocation for a new Document, and avoiding copying/deepCopy json Values between two different documents, I need to use the same Document's memory to do everything related. Am i right?
  2. As commented in the code, doc = parse(str, doc.GetAllocator()); this snippet will cause segment fault error in the second time when str = string2, could you please tell me why?

Thanks in advance!

Most helpful comment

Yes. You should not assign to the doc because it destroys the allocator in it.
But I am not sure why you need this. Why not just simply doc.Parse(json)?

All 3 comments

I guess i've got to know the reason about the problem 2:

Before

    for (const auto& str : vec) {
        doc = parse(str, doc.GetAllocator());  // here will cause SIGSEGV error in the second loop
        std::cerr << "doc : " << rapidjsonValueToString(doc) << std::endl;
    }

After

    for (const auto& str : vec) {
        auto d = parse(str, doc.GetAllocator());  // save the parse result in d
        Pointer().Get(d)->Swap(doc);             // get the root of d, and then swap with doc
        std::cerr << "doc : " << rapidjsonValueToString(doc) << std::endl;
    }

Although this solve the problem, but i'm not sure whether this is recommended way?
Or does anyone have better solutions ?

Yes. You should not assign to the doc because it destroys the allocator in it.
But I am not sure why you need this. Why not just simply doc.Parse(json)?

@miloyip , Thanks for your reply.
Yes, You are right.
I just want to use the same document's memory allocator for parse multiple times, and avoid copy operations as possible.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

OlafvdSpek picture OlafvdSpek  路  6Comments

dan-ryan picture dan-ryan  路  6Comments

lelit picture lelit  路  5Comments

vzaluckis picture vzaluckis  路  4Comments

oneonce picture oneonce  路  3Comments