Неправильное заполнения rapidjson документа. Assert при попытке найти данные
есть вот такой код.
#include <iostream>
#include <vector>
#include <rapidjson.h>
#include <document.h>
#include <writer.h>
#include <stringbuffer.h>
using namespace std;
enum AccessLvl {
LOW = 0,
AVERAGE = 1,
HIGH = 2
};
class Message {
public:
Message(std::string login,
std::string loginColor,
std::string imageSource,
std::string message,
std::string time,
bool firstmessage)
: _login(login),
_loginColor(loginColor),
_imageSource(imageSource),
_message(message),
_time(time),
_firstmessage(firstmessage){};
public:
rapidjson::Document to_json();
private:
std::string _login;
std::string _loginColor;
std::string _imageSource;
std::string _message;
std::string _time;
bool _firstmessage;
};
class Contacts {
public:
Contacts(std::string username, std::string imageSource, std::string lastMessage, std::vector<Message> messages)
: _username(username),
_imageSource(imageSource),
_lastMessage(lastMessage),
_messages(messages) {};
public:
rapidjson::Document to_json();
private:
std::string _username;
std::string _imageSource;
std::string _lastMessage;
std::vector<Message> _messages;
};
class PersonalData {
public:
PersonalData(std::string name, std::string surname, std::string patronumic, std::string yearsold)
: _name(name),
_surname(surname),
_patronymic(patronumic),
_yearsold(yearsold) {};
PersonalData(const PersonalData& pd)
: _name(pd._name),
_surname(pd._surname),
_patronymic(pd._patronymic),
_yearsold(pd._yearsold) {};
PersonalData() {};
public:
rapidjson::Document to_json();
public:
std::string _name;
std::string _surname;
std::string _patronymic;
std::string _yearsold;
};
class User {
public:
User(std::string imageSource,
std::string login,
std::string pass,
std::vector<Contacts> contacts,
AccessLvl accessLvl,
PersonalData personalData);
User(const User &user);
User(User &user);
public:
rapidjson::Document to_json();
PersonalData* get_personalData();
AccessLvl get_access_lvl();
std::string get_login();
std::string get_pass();
void show_data();
int get_id();
private:
int _id;
std::string _imageSource;
std::string _login;
std::string _password;
std::vector<Contacts> _contacts;
AccessLvl _accessLvl;
PersonalData* _personalData;
};
User::User(std::string imageSource,
std::string login,
std::string pass,
std::vector<Contacts> contacts,
AccessLvl accessLvl,
PersonalData personalData)
{
_imageSource = imageSource;
_login = login;
_password = pass;
_accessLvl = accessLvl;
_personalData = new PersonalData(personalData);
_contacts = contacts;
}
User::User(User &user) {
_login = user._login;
_password = user._password;
_accessLvl = user._accessLvl;
_personalData = user._personalData;
}
User::User(const User &user) {
_login = user._login;
_password = user._password;
_accessLvl = user._accessLvl;
_personalData = user._personalData;
}
rapidjson::Document User::to_json(){
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
rapidjson::Value jsonUser(rapidjson::kObjectType);
rapidjson::Value login;
rapidjson::Value password;
rapidjson::Value jsonContacts(rapidjson::kArrayType);
rapidjson::Value accessLvl;
rapidjson::Value personalData(rapidjson::kObjectType);
for (int i = 0; i < _contacts.size(); ++i) {
jsonContacts.PushBack(_contacts[i].to_json(),allocator);
}
login.SetString(_login.c_str(), _login.size(),allocator);
password.SetString(_password.c_str(), _password.size(),allocator);
accessLvl.SetInt64(_accessLvl);
personalData.AddMember("personalData", _personalData->to_json(),allocator);
jsonUser.AddMember("login", login,allocator);
jsonUser.AddMember("password", password,allocator);
jsonUser.AddMember("contacts", jsonContacts,allocator);
jsonUser.AddMember("accessLvl", accessLvl,allocator);
jsonUser.AddMember("personalData", personalData, allocator);
document.AddMember("user", jsonUser, allocator);
return document;
}
rapidjson::Document PersonalData::to_json() {
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
rapidjson::Value jsonPersonalData(rapidjson::kObjectType);
rapidjson::Value name;
rapidjson::Value surname;
rapidjson::Value patronymic;
rapidjson::Value yearsold;
name.SetString(_name.c_str(), _name.size(),allocator);
surname.SetString(_surname.c_str(), _surname.size(),allocator);
patronymic.SetString(_patronymic.c_str(), _patronymic.size(),allocator);
yearsold.SetString(_yearsold.c_str(), _yearsold.size(),allocator);
jsonPersonalData.AddMember("name", name,allocator);
jsonPersonalData.AddMember("surname", surname,allocator);
jsonPersonalData.AddMember("patronymic", patronymic,allocator);
jsonPersonalData.AddMember("yearsold", yearsold,allocator);
document.AddMember("personalData", jsonPersonalData, allocator);
return document;
}
rapidjson::Document Contacts::to_json() {
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
rapidjson::Value jsonContact(rapidjson::kObjectType);
rapidjson::Value username;
rapidjson::Value imageSource;
rapidjson::Value lastMessage;
rapidjson::Value jsonMessages(rapidjson::kArrayType);
rapidjson::Value messages(rapidjson::kArrayType);
for (int i = 0; i < _messages.size(); ++i) {
messages.PushBack(_messages[i].to_json(),allocator);
}
username.SetString(_username.c_str(), _username.size(),allocator);
imageSource.SetString(_imageSource.c_str(), _imageSource.size(),allocator);
lastMessage.SetString(_lastMessage.c_str(), _lastMessage.size(),allocator);
jsonContact.AddMember("username", username ,allocator);
jsonContact.AddMember("image_source", imageSource,allocator);
jsonContact.AddMember("last_message", lastMessage,allocator);
jsonContact.AddMember("messages", messages,allocator);
document.AddMember("contact", jsonContact, allocator);
return document;
}
rapidjson::Document Message::to_json() {
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
rapidjson::Value jsonMessage(rapidjson::kObjectType);
rapidjson::Value login;
rapidjson::Value loginColor;
rapidjson::Value imageSource;
rapidjson::Value message;
rapidjson::Value time;
rapidjson::Value firstMessage;
login.SetString(_login.c_str(), _login.size(),allocator);
loginColor.SetString(_loginColor.c_str(), _loginColor.size(),allocator);
imageSource.SetString(_imageSource.c_str(), _imageSource.size(),allocator);
message.SetString(_message.c_str(), _message.size(),allocator);
time.SetString(_time.c_str(), _time.size(),allocator);
firstMessage.SetBool(_firstmessage);
jsonMessage.AddMember("login", login ,allocator);
jsonMessage.AddMember("login_color", loginColor,allocator);
jsonMessage.AddMember("image_source", imageSource,allocator);
jsonMessage.AddMember("message", message,allocator);
jsonMessage.AddMember("time", time,allocator);
jsonMessage.AddMember("firstMessage", firstMessage,allocator);
if(document.IsObject())
document.AddMember("message", jsonMessage, document.GetAllocator());
else
std::cout << "ERROR";
return document;
}
void WriteDocumentToString(const rapidjson::Document& document, std::string& output) {
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
output = buffer.GetString();
}
int main() {
Message msg1("Admin", "Green", "link.com", "message bla bla bla", "11:24", true);
Message msg2("Admin", "Green", "link.com", "message bla bla bla", "11:25", true);
Message msg3("Admin", "Green", "link.com", "message bla bla bla", "11:26", true);
std::vector<Message> messages;
messages.push_back(msg1);
messages.push_back(msg2);
messages.push_back(msg3);
Contacts cont1("Lexa", "image.com", "bla bla bla", messages);
Contacts cont2("Stepan", "image.com", "bla bla bla", messages);
Contacts cont3("Oleg", "image.com", "bla bla bla", messages);
std::vector<Contacts> contacts;
contacts.push_back(cont1);
contacts.push_back(cont2);
contacts.push_back(cont3);
PersonalData pd("Dima","Lol","Ivanovich","13.12.1998");
User test("image.com", "Admin", "Admin", contacts, HIGH, pd);
std::string json;
rapidjson::Document doc;
try {
WriteDocumentToString(test.to_json(), json);
} catch (std::exception& ex) {
std::cout << ex.what() << std::endl;
}
return 0;
}
Ошибка при попытке записать документ в строку
WriteDocumentToString(test.to_json(), json);
Signal: SIGSEGV (Segmentation fault)
Ответы (1 шт):
Автор решения: lbsmart
→ Ссылка
Проблема была в аллокаторых которые уничтожались при выходе из функции. Многие примеры RapidJSON говорят вам использовать такие вызовы, как:
Document d;
doc.AddMember("txt", smth , doc.GetAllocator());
Но подход всегда использовать doc.GetAllocator() работает только для простых примеров.
Причина segfault, по-видимому, заключается в том, что как только Document объект выходит за пределы области видимости, его экземпляр распределителя освобождается, и, следовательно, память будет использоваться повторно.
Решение:
#include <iostream>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/ostreamwrapper.h>
using namespace rapidjson;
using namespace std;
MemoryPoolAllocator<> jsonAlloc; // Это по сути и является решением, создание общего аллокатора
Document generateInnerDoc() {
Document doc;
doc.SetObject(); // Make doc an object !
doc.AddMember("text", Value().SetString("Hello JSON!"), jsonAlloc);
return doc;
}
Document generateOuterDoc() {
Document doc;
doc.SetObject(); // Make doc an object !
doc.AddMember("text", generateInnerDoc(), jsonAlloc);
return doc;
}
int main() {
OStreamWrapper out(cout);
Writer<OStreamWrapper> writer(out);
generateOuterDoc().Accept(writer);
}