При суммировании класса строк исчезает правый операнд

string json

Я собираюсь создать функцию для jsify содержимого датчиков и сохранить его на SD-карте или отправить через http-клиент. За исключением Serial.println, функция расшифрована ниже.

String jsonificar(vector<vector<String>> sujeito){
  String json_txt = String(""), chave, valor;
  String chave_str, valor_str;

  json_txt+=String("{");
  for(unsigned int i = 0; i<sujeito.size(); i++){
    if(sujeito[i].size() != 2){
        Serial.println("Cada conteudo deve conter 2 textos!");
    }
    else{
        chave = sujeito[i][0];
        valor = sujeito[i][1];
        Serial.println(chave);
        Serial.println(valor);
        Serial.println(json_txt);
        json_txt += "\\\"";
        Serial.println(json_txt);
        json_txt += chave;
        Serial.println(json_txt);
        json_txt += "\\\"";
        Serial.println(json_txt);
        json_txt += ":";
        Serial.println(json_txt);
        json_txt += "\\\"";
        Serial.println(json_txt);
        json_txt += valor;
        Serial.println(json_txt);
        json_txt += "\\\"";
        Serial.println(json_txt);

        if(i != sujeito.size() - 1){
          json_txt += String(",");
        }
    }
  }

  json_txt+="}";
  Serial.println(json_txt);

  return json_txt;
}

Вывод на последовательный порт следующий:

Output:

Chave1
Valor1
{
{\"
{\"Chave1
{\"Chave1\"
{\"Chave1\":
{\"Chave1\":\"
{\"Chave1\":\"Valor1
{\"Chave1\":\"Valor1\"
Chave2
Valor2
{\"Chave1\":\"Valor1\",
{\"Chave1\":\"Valor1\",\"
{\"Chave1\":\"Valor1\",\"    <===
{\"Chave1\":\"Valor1\",\"\"
{\"Chave1\":\"Valor1\",\"\": <===
{\"Chave1\":\"Valor1\",\"\": <===
{\"Chave1\":\"Valor1\",\"\": <===
{\"Chave1\":\"Valor1\",\"\": <===
{\"Chave1\":\"Valor1\",\"\":}

Стрелки показывают места, где логи отличаются от ожидаемых: предоставленные ключи и значения: "Chave1", "Valor1", "Chave2", "Valor2". Таким образом, ключ-значение должно быть "Chave2":"Valor2". Вы понимаете это поведение? С нетерпением жду ответа!

, 👍0

Обсуждение

Как вы засунули std::vector в Arduino? У меня не компилируется., @Maximilian Gerhardt

Тот же способ, который можно использовать в приложении C++ по умолчанию: using namespace std; Вы непреднамеренно ответили на свой собственный вопрос ;P, @Bruno Henrique Peixoto

Реализация ядра Arduino для AVR не имеет этих типов C++ STL. Используете ли вы дополнительную библиотеку, например https://github.com/mike-matera/ArduinoSTL ?, @Maximilian Gerhardt

Да, я использую ArduinoSTL. Я также использую PlatformIO в качестве IDE, и там написано, что vector происходит из namespace std., @Bruno Henrique Peixoto

Вы **должны** использовать эту библиотеку, без сомнения. Без нее она не работает. Я скомпилировал этот код, и он запустился без ошибок. Посмотрите: https://pastebin.com/LPTYDje5, @Maximilian Gerhardt

Обратите внимание, что вы создаете строки, которые используют динамическое распределение памяти. Какой у вас MCU? Arduino Uno? Вы можете видеть, что мой минимальный тестовый скетч работает, так что если в вашем случае он не работает, у вас закончилась память. Какой именно скетч вы используете?, @Maximilian Gerhardt

#include <Arduino.h> #include <unity.h> #include "../src/utils.h" вектор<String> vetor_auxiliar1, vetor_auxiliar2; вектор<вектор<Строка>> vetor_mestre; , @Bruno Henrique Peixoto

void test_jsonificar(){ vetor_auxiliar1.push_back(String("Chave1")); vetor_auxiliar1.push_back(String("Valor1")); vetor_mestre.push_back(vetor_auxiliar1); vector_auxiliar2.push_back(String("Ключ2")); vector_auxiliar2.push_back(String("Значение2")); vector_master.push_back(vector_auxiliary2); Результат строки, ожидаемый = String("{\"Key1\":\"Value1\",\"Key2\":\"Value2\"}"); результат = jsonify(master_vector); TEST_ASSERT_EQUAL(1, ожидаемое.сравнениеС(результат)); } , @Bruno Henrique Peixoto

void setup() { Последовательный.начало(9600); UNITY_BEGIN(); } недействительный цикл() { RUN_TEST(test_jsonify); UNITY_END(); // остановить модульное тестирование }, @Bruno Henrique Peixoto

Хорошо, вам следовало бы отредактировать свой вопрос с этим кодом, но когда я запускаю его (без фреймворка Unity Testing), я получаю поведение, при котором он падает после третьей итерации (при помещении в цикл). Я бы просто использовал библиотеку https://github.com/bblanchon/ArduinoJson для создания этих строк JSON более эффективным с точки зрения памяти способом, чем конкатенация String, которая использует кучу кучи (https://pastebin.com/h2eE3sgc), @Maximilian Gerhardt

Хорошо, я так и сделаю. Спасибо за консультацию., @Bruno Henrique Peixoto


1 ответ


Лучший ответ:

3

Ваша «исчезающая строка» имеет следующую причину: нехватка памяти.

Вы создаете множество объектов String в своем коде и объединяете их в один. Это использует память в куче для каждого Stringrealloc(), когда память String должна быть расширена).

Рассмотрите следующий тестовый набросок, который включает ваш код, но также добавляет утечку памяти на 150 байт в каждой итерации:

#include <Arduino.h>
#include <ArduinoSTL.h>
using namespace std;

extern unsigned int __heap_start;
extern void *__brkval;

/*
* Структура свободного списка, поддерживаемая
* Процедуры выделения памяти avr-libc.
*/
struct __freelist {
    size_t sz;
    struct __freelist *nx;
};

/* The head of the free list structure */
extern struct __freelist *__flp;

/* Calculates the size of the free list */
int freeListSize() {
    struct __freelist* current;
    int total = 0;
    for (current = __flp; current; current = current->nx) {
        total += 2; /* Add two bytes for the memory block's header  */
        total += (int) current->sz;
    }
    return total;
}

int freeMemory() {
    int free_memory;
    if ((int) __brkval == 0) {
        free_memory = ((int) &free_memory) - ((int) &__heap_start);
    } else {
        free_memory = ((int) &free_memory) - ((int) __brkval);
        free_memory += freeListSize();
    }
    return free_memory;
}

String jsonificar(vector<vector<String>> sujeito) {
    String json_txt = String(""), chave, valor;
    String chave_str, valor_str;

    json_txt += String("{");
    for (unsigned int i = 0; i < sujeito.size(); i++) {
        if (sujeito[i].size() != 2) {
            Serial.println("Cada conteudo deve conter 2 textos!");
        } else {
            chave = sujeito[i][0];
            valor = sujeito[i][1];
            Serial.println(chave);
            Serial.println(valor);
            Serial.println(json_txt);
            json_txt += "\\\"";
            Serial.println(json_txt);
            json_txt += chave;
            Serial.println(json_txt);
            json_txt += "\\\"";
            Serial.println(json_txt);
            json_txt += ":";
            Serial.println(json_txt);
            json_txt += "\\\"";
            Serial.println(json_txt);
            json_txt += valor;
            Serial.println(json_txt);
            json_txt += "\\\"";
            Serial.println(json_txt);

            if (i != sujeito.size() - 1) {
                json_txt += String(",");
            }
        }
    }

    json_txt += "}";
    Serial.println(json_txt);

    return json_txt;
}

void setup(void) {
    Serial.begin(115200);
}

String myStr = "";

void loop(void) {

    Serial.print(F("Free Memory:"));
    Serial.println(freeMemory());

    //вызвать утечку памяти, выделив добавление к глобальной строке
    myStr +=
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

    vector<vector<String>> v =
            { { "Chave1", "Valor1" }, { "Chave2", "Valor2" }, };

    jsonificar(v);
    delay(1000);
}

Из выходных данных мы можем увидеть точную точку, где у нас достаточно памяти и результат правильный, и где у нас недостаточно памяти и строка просто «исчезает», потому что не хватило памяти для ее выделения:

Free Memory:911
Chave1
Valor1
{
{\"
{\"Chave1
{\"Chave1\"
{\"Chave1\":
{\"Chave1\":\"
{\"Chave1\":\"Valor1
{\"Chave1\":\"Valor1\"
Chave2
Valor2
{\"Chave1\":\"Valor1\",
{\"Chave1\":\"Valor1\",\"
{\"Chave1\":\"Valor1\",\"Chave2
{\"Chave1\":\"Valor1\",\"Chave2\"
{\"Chave1\":\"Valor1\",\"Chave2\":
{\"Chave1\":\"Valor1\",\"Chave2\":\"
{\"Chave1\":\"Valor1\",\"Chave2\":\"Valor2
{\"Chave1\":\"Valor1\",\"Chave2\":\"Valor2\"
{\"Chave1\":\"Valor1\",\"Chave2\":\"Valor2\"}
Free Memory:761
Chave1
Valor1
{
{\"
{\"Chave1
{\"Chave1\"
{\"Chave1\":
{\"Chave1\":\"
{\"Chave1\":\"Valor1
{\"Chave1\":\"Valor1\"
Chave2
Valor2
{\"Chave1\":\"Valor1\",
{\"Chave1\":\"Valor1\",\"
{\"Chave1\":\"Valor1\",\"Chave2
{\"Chave1\":\"Valor1\",\"Chave2\"
{\"Chave1\":\"Valor1\",\"Chave2\":
{\"Chave1\":\"Valor1\",\"Chave2\":\"
{\"Chave1\":\"Valor1\",\"Chave2\":\"
{\"Chave1\":\"Valor1\",\"Chave2\":\"
{\"Chave1\":\"Valor1\",\"Chave2\":\"
,