缓冲区被覆盖
Buffer gets overwritten
我在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.h
和ConfigManager.cpp
*我宁愿在评论中写下,因为我没有 arduino,也无法验证我的建议是否 100% 有用。但我不能使用带有"我的声誉":)的评论。所以如果我的答案没有帮助,请不要按"减号按钮"......
*据此,在使用 json 缓冲区时,您似乎需要保留原始 json 字符串。
- 将 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是否正确删除数组。
- C++字符*缓冲区的大小
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- 使用ios:ate写入到流会覆盖现有文件
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- Xaudio2在更改缓冲区或循环时弹出声音
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 多线程双缓冲区
- 我可以重新分配/覆盖std::字符串吗
- Android P-9.0.0_r53 Logcat主缓冲区超出定义大小
- 套接字读取后,我在缓冲区中看到意外输入
- 叮叮当当在修复时插入多个"覆盖"说明符
- 谷歌模拟和覆盖关键字
- 缓冲区被覆盖
- 为什么我的程序一直给我堆缓冲区溢出,即使我没有超出数组的界限或覆盖任何值
- 如何清理(用随机字节覆盖)std::string内部缓冲区
- WriteFile成功,即使缓冲区被挂起的操作覆盖