c++ - 缓冲区被覆盖

标签 c++ buffer

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

我对像 c/c++ 这样的本地语言没有太多经验,而且我正面临一个奇怪的问题,这让我发疯。所以我使用的是 Wemos D1 mini (ESP8266),它使用类调用 ConfigManager 从 eeprom 读取配置文件。配置文件格式为 json,所以我使用 ArduinoJson解析内容。我在 header 中声明了一个 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对象的内容打印到log中,不过这次好像有什么东西覆盖了JsonBuffer,导致json对象被损坏。这次记录的内容是 {"v␂":"0.2","led_count":"64"}(带有一些奇怪的 unicorn 字符,随着源代码的变化而变化)。我试图弄清楚现在好几个小时发生了什么,但我被困住了。有人可以指出我正确的方向来解决这个问题吗?谢谢!

可以找到完整的日志HERE ,以及 ConfigManager.hConfigManager.cpp

最佳答案

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

根据 that看来您在使用 json 缓冲区时需要保留原始 json 字符串。

  1. Keep the JSON string in memory long enough

The library never make memory duplication. This has an important implication on string values, it means that the library will return pointer to chunks of the string.

For instance, let’s imagine that you parse ["hello","world"], like this:

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

StaticJsonBuffer<32> buffer;

JsonArray& array = buffer.parseArray(json);

const char* first = array[0];

const char* second = array[1];

In that case, both first and second are pointers to the content of the original string json. So this will only work if json is still in memory.

因此,尝试使 std::unique_ptr buf 成为类成员(与 StaticJsonBuffer 相同)并检查其工作原理是有意义的。

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

关于c++ - 缓冲区被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48871543/

相关文章:

Android ListView 缓冲区

c# - 有没有办法知道FileSystemwatcher还剩下多少缓冲区?

c - 是否可以直接从文件写入套接字?

javascript - 将 byteArray 保存为 Titanium 中的 pdf 文件

c++ - DeviceContext (HDC) 中的 Alpha channel

c - 缓冲区溢出或其他

c++ - 使 int vector 从具有 int 的类的 vector 中接收值

c++ - 如何在 z3 c++ 界面中启用校样?

c++ - 哪些客户正在使用驱动程序?

c++ - 如何将 bitset 转换为字节数组/uint8?