缓冲区被覆盖

时间:2018-02-19 17:45:37

标签: c++ buffer

我在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.hConfigManager.cpp

1 个答案:

答案 0 :(得分:3)

*我更喜欢在评论中写一下,因为我没有arduino并且无法验证我的建议100%有用。但我不能用&#34;我的声誉和#34; :)。所以请不要按&#34;减号按钮&#34;如果我的回答没有帮助...... *

根据that,你似乎需要在使用json缓冲区时保留原始的json字符串。

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

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

         

    例如,让我们假设您解析[&#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是否正确删除了数组。