我在ESP8266(类似Arduino的主板)上面对这个问题,但这个问题与c / c ++有关,所以我在这里问这个问题。
我对c / c ++这样的母语没有太多经验,我面临一个奇怪的问题,这让我发疯。所以我使用的是Wemos D1 mini(ESP8266),它使用类calles ConfigManager
从eeprom读取配置文件。配置文件格式为json,因此我使用ArduinoJson来解析内容。我在标题中声明了StaticJsonBuffer
和指向JsonObject
的指针,就像您在代码示例中看到的那样:
//FILE: ConfigManager.h
#ifndef ConfigManager_H
#define ConfigManager_H
#include <Arduino.h>
#include <ArduinoJson.h>
#include <FS.h>
#include "Logger.h"
class ConfigManager {
public:
Settings *settings;
ConfigManager();
void read_from_eeprom();
private:
File configFile;
JsonObject *json;
StaticJsonBuffer<200> jsonBuffer;
void open_file(const char *permission);
void read_json();
void recreate_file();
void create_json();
void check_success();
void populate_settings();
void clean_up();
};
#endif
当调用函数read_from_eeprom
时,它会打开文件并调用函数read_json
:
void ConfigManager::read_json() {
size_t size = configFile.size();
Log.verbose("[ConfigManager] Config file size: %d", size);
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
Log.verbose("[ConfigManager] File content: %s", buf.get());
Log.verbose("[ConfigManager] Parsing json");
json = &jsonBuffer.parseObject(buf.get());
Log.notice("[ConfigManager] Json is:");
json->printTo(Serial);
Serial.println();
}
然后调用check_success()
void ConfigManager::check_success() {
Log.notice("[ConfigManager] Json is:");
json->printTo(Serial);
Serial.println();
bool should_recreate = true;
if (json->success()) {
Log.notice("[ConfigManager] Parsed json successfully");
auto version = json->get<const char*>("version");
if (version) {
if (strcmp(version, Settings::current_version) == 0) {
Log.notice("[ConfigManager] Config version is up2date");
should_recreate = false;
} else {
Log.warning("[ConfigManager] Config version outdated");
}
} else {
Log.warning("[ConfigManager] Invalid config file");
}
} else {
Log.warning("[ConfigManager] Config file is not valid json");
}
if (should_recreate) {
Log.notice("[ConfigManager] Recreating config file");
recreate_file();
create_json();
}
Log.notice("JSON IS: ");
json->prettyPrintTo(Serial);
Log.notice("[ConfigManager] Sucessfully read json");
}
所以我注意到文件内容很好。例如。 {"version":"0.2","led_count":"64"}
。
然后解析json,成功并记录json对象,这又是{"version":"0.2","led_count":"64"}
。
之后函数返回,并调用check_success
,它再次将json对象的内容打印到日志中,但这次似乎有些东西覆盖了JsonBuffer,导致json对象被破坏。这次记录的内容为{"v␂":"0.2","led_count":"64"}
(一些奇怪的独角兽角色会随着源代码的变化而变化)。我试图弄清楚现在发生了多少小时,但是我被卡住了。有人可以指出我正确的方向来解决这个问题吗?谢谢!
可以找到完整的日志HERE,以及ConfigManager.h
和ConfigManager.cpp
答案 0 :(得分:3)
*我更喜欢在评论中写一下,因为我没有arduino并且无法验证我的建议100%有用。但我不能用&#34;我的声誉和#34; :)。所以请不要按&#34;减号按钮&#34;如果我的回答没有帮助...... *
根据that,你似乎需要在使用json缓冲区时保留原始的json字符串。
- 将JSON字符串保留在内存中足够长的时间
醇>库从不进行内存复制。这对字符串有重要意义 值,这意味着库将返回指向块的指针 字符串。
例如,让我们假设您解析[&#34; hello&#34;,&#34; world&#34;],就像 这样:
char [] json =&#34; [\&#34; hello \&#34;,\&#34; world \&#34;]&#34 ;;
StaticJsonBuffer&LT 32取代;缓冲;
JsonArray&安培; array = buffer.parseArray(json);
const char * first = array [0];
const char * second = array [1];
在那 case,第一个和第二个都是指向内容的指针 原始字符串json。所以这只有在json还在的情况下才有效 存储器中。
因此,尝试使std :: unique_ptr buf成为一个类成员(与StaticJsonBuffer相同)并检查它是如何工作的。
顺便说一下,IMO std :: vector会更合适......而且我不确定unique_ptr是否正确删除了数组。