缓冲区被覆盖

Buffer gets overwritten

本文关键字:覆盖 缓冲区      更新时间:2023-10-16

我在ESP8266(类似Arduino的板)上遇到了这个问题,但这个问题是关于c/c ++的,所以我在这里问这个问题。

我对 c/c++ 等母语没有太多经验,我面临着一个奇怪的问题,这让我发疯。所以我使用的是 Wemos D1 mini (ESP8266),它使用类调用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"}(有一些奇怪的独角兽字符会随着源代码的变化而变化)。我试图弄清楚发生了什么,现在好几个小时了,但我被卡住了。有人可以指出我解决这个问题的正确方向吗?谢谢!

完整的日志可以在这里找到,以及ConfigManager.hConfigManager.cpp

*我宁愿在评论中写下,因为我没有 arduino,也无法验证我的建议是否 100% 有用。但我不能使用带有"我的声誉":)的评论。所以如果我的答案没有帮助,请不要按"减号按钮"......

*据此,在使用 json 缓冲区时,您似乎需要保留原始 json 字符串。

  1. 将 JSON 字符串保留在内存中足够长的时间

库从不进行内存重复。这对字符串有重要意义 值,这意味着库将返回指向 字符串。

例如,假设您解析 ["hello","world"],例如 这:

char[] json = "[\"hello\",\"world\"]";

StaticJsonBuffer<32> buffer;

JsonArray&array = buffer.parseArray(json);

常量字符* 首先 = 数组[0];

常量字符* 秒 = 数组[1];

在那 案例,第一个和第二个都是指向 原始字符串 JSON。所以这只有在 json 仍在时才有效 记忆。

因此,尝试将 std::unique_ptr buf 设置为类成员(与 StaticJsonBuffer 相同)并检查它是如何工作的,这是有意义的。

顺便说一句,IMO std::vector将更适合那里...而且我不确定unique_ptr是否正确删除数组。