【发布时间】:2021-09-07 04:12:44
【问题描述】:
所以我有一个简单的类,它接受一个字符数组并将其解析为一个 JSON 对象。然后它在内部存储该对象并提供一个 getter。
class JSONContainer {
public:
explicit JSONContainer(const char* const json) {
std::string t(json);
_json = new nlohmann::basic_json(json);
}
~JSONContainer() {
delete _json;
}
nlohmann::json *j() {
return _json;
}
private:
nlohmann::json* _json;
};
如果我用一些简单的东西来实例化这个类......
{"data": [100,100]}
它可以工作,但是如果这个字符串增长到 ~1000+ 的长度,当我尝试将 json 解析为一个字符串时,传入的字符数组就会损坏。
// incoming json {"data": [100,100,100,100,100...
std::string t(json); // turns into "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ..." after this line
我不知道是什么原因造成的。我想检查的一件事是 json 末尾是否存在空终止符,我总是找到它。
感谢您的帮助!
cmets 的附加上下文 ...
这是调用上面构造函数的方法……
std::shared_ptr<void> JSONSerDes::deserialize(const char *serializedData) {
auto *ct = new JSONContainer(serializedData);
return std::shared_ptr<void>(ct);
}
然后上栈到主函数,注意这一行deserializedData = t->deserialize(serializedData); ...
...
// declare intermediate data
const char* serializedData;
std::shared_ptr<void> deserializedData;
// for each data set size, run each test
for (const int testSize: sizeTestsB) {
// generate the test data, imitate data coming from python program
PyObject* td = data(testSize);
for (const std::unique_ptr<SerDesTest>& t: tests) {
// log the start
startTest(t->type(), testSize, currentTest, totalTests);
// mark start, ser/des mark end
start = std::chrono::steady_clock::now();
serializedData = t->serialize(td); // Python -> Redis
checkpoints.push_back(checkpoint(t->type(), testSize, "PythonToRedis", start));
deserializedData = t->deserialize(serializedData); // Redis -> Container
checkpoints.push_back(checkpoint(t->type(), testSize, "RedisToContainer", start));
...
这是用于将python对象转换为字符数组的函数。 dumps 是来自 pythons json 模块的一种方法。我可能误解了字符数组的生命周期是什么。
const char* JSONSerDes::serialize(PyObject * pyJson) {
// convert pyobject to boost python object
boost::python::object d = boost::python::extract<boost::python::object>(pyJson);
// call the dumps function and capture the return value
return boost::python::extract<const char*>(dumps(d));
}
【问题讨论】:
-
能否展示构造代码,包括构造函数参数的生命周期相关代码?
-
@SR_ 更改帖子以提供更多上下文。
-
t->serialize(td)返回什么?我的猜测是它返回一个指向已释放std::string的指针,因此该值对于短字符串(小字符串优化)设法保持活动状态,但对于长字符串(溢出到堆上)失败。字符Í是十六进制0xCD,是常用的调试填充值。根据this table,它被MSVC用于未初始化的堆数据。 (还要注意shared_ptr<void>将是内存泄漏,因为它不知道如何破坏JSONContainer。) -
@RaymondChen 它返回一个字符数组,表示可以写入文件/写入redis的数据缓冲区。我也在我的帖子中包含了该方法。我不知道如何在堆上创建一个 json 对象,所以这就是我创建该容器对象的原因。如您所见,我仍在学习,因此非常感谢您提出任何建议
-
我更新了我的帖子以包含一个具有析构函数的新容器,行为相同
标签: c++ stdstring nlohmann-json c-str