При суммировании класса строк исчезает правый операнд
Я собираюсь создать функцию для 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". Вы понимаете это поведение? С нетерпением жду ответа!
1 ответ
Лучший ответ:
Ваша «исчезающая строка» имеет следующую причину: нехватка памяти.
Вы создаете множество объектов String
в своем коде и объединяете их в один. Это использует память в куче для каждого String
(и realloc()
, когда память 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\":\"
- Удаление нежелательных символов из типа char
- Второй элемент в массиве не назначается из объекта структуры, ArduinoJson
- Как правильно обрабатывать строку Arduino
- ArduinoJSON: использование ссылки на ссылку при анализе массива массивов
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- форматирование строк в Arduino для вывода
- Очень простая операция Arduino Uno Serial.readString()
Как вы засунули
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 Peixotovoid 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 Peixotovoid 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