Есть ли объяснение такому поведению?
Для приведенного ниже фрагмента кода
const char* fr_fbdb(char tag[30]) // fn для извлечения данных
{
char full_path[120];
const char *_dt ;
strcpy(full_path , base_path);
strcat(full_path , tag);
Serial.print( "retrieving from " );
Serial.println(full_path) ;
Firebase.get(firebaseData, full_path);
_dt = firebaseData.cstrData();
// Serial.print("while ext: ");
// Serial.println(_dt);
return _dt ;
}
void retreive_sch()
{
int no_tag = strlen(*tag) ;
//Serial.print("количество тегов в БД: ");
//Serial.println(no_tag);
const char *_data[no_tag];
Firebase.get(firebaseData, "/SCHEDULE DETAILS/SELECTED");
sch_no = firebaseData.cstrData();
Serial.print("extracting schedule");
Serial.println(sch_no);
strcat(base_path , sch_no); // базовый путь w/ sch no.
for (int i = 0 ; i < 6 ; i++)
{
_data[i] = fr_fbdb(tag[i]);
Serial.print("while ext: ");
Serial.println(_data[i]);
}
for(int i=0 ; i<6 ; i++)
{
Serial.print("after extraction:");
Serial.println(_data[i]) ;
}
}
Вот результат:
retrieving schedule changes -- setup
extracting schedule3
retrieving from /SCHEDULE DETAILS/SCHEDULE3/DATE
while ext: [1609612200000,\"inf\"]
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ FR
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ TO
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/WEIGHT
while ext: 29
retrieving from /SCHEDULE DETAILS/SCHEDULE3/TIME
while ext: \"6:30\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/frequency
while ext: \"-1\"
after extraction:"root":[]
after extraction:\"-1\"
after extraction:keep-alive
after extraction:\"-1\"
after extraction:"root":[]
after extraction:\"-1\"
Как вы можете видеть, вывод одной и той же переменной _data[]
внутри этой конкретной функции изменяется.
Есть идеи, почему?
1 ответ
Проблема заключается в следующих строках кода в вашей функции fr_fddb()
:
Firebase.get(firebaseData, full_path);
_dt = firebaseData.cstrData();
Вы не поделились достаточным количеством кода, чтобы прояснить это, но firebaseData, по-
видимому, является глобальным, который вы повторно используете. Когда вы вызываете его метод .cstrData ()
, вы каждый раз получаете указатель на один и тот же буфер, и этот буфер перезаписывается каждый раз, когда вы вызываете Firebase.get()
.
Вы можете проверить это, печатая значение указателя каждый раз, как это делается в вашей функции retrieve_sch ()
:
for (int i = 0 ; i < 6 ; i++)
{
_data[i] = fr_fbdb(tag[i]);
Serial.print("while ext: ");
Serial.println(_data[i]);
Serial.printf("_data[i] pointer %p\n", _data[i]);
}
Скорее всего, вы увидите, что 6 указателей идентичны. Значение меняется, потому что вы продолжаете повторно использовать одну и ту же строку.
Простое решение заключается в следующем:
Firebase.get(firebaseData, full_path);
_dt = strdup(firebaseData.cstrData());
Это выделяет память и сохраняет в ней дубликат строки, полученной из Firebase. Теперь ваша функция вернет это, и firebaseData
можно будет безопасно использовать повторно.
Это решение потребует от вас освободить эту память в какой-то момент, когда вы используете ее, вызвав free(_dt);
или что бы вы ни держали указатель, когда закончите. Я оставляю это как упражнение для вас.
- Чтение строки из Firebase и сохранение ее в виде CString
- Как заменить объекты String массивами символов, продолжая использовать строковые методы
- форматирование строк в Arduino для вывода
- Простой запрос GET с ESP8266HTTPClient
- Проблемы с преобразованием byte[] в String
- Преобразование строки в IP-адрес
- Чтение строки, разделенной запятыми
- Как составить URL-адрес HTTP-запроса GET с параметрами ключ/значение
Я бы посоветовал вам взять книгу о C++ и понять, как использовать const, что происходит и область действия локально объявленной переменной внутри функции., @hcheung
`_data
- это глобальный var, и оба набора операторов печати находятся в одном и том же Fn. Я использовал
const char* fr_fbdb
bcos
firebaseData.cstrData()
возвращает c-строку. Вот как я думал, что поток будет: я вызываю
retrieve_sch ()в
setup (). Тогда я получаю "нет". из тегов из
strlen(*tag)
(
tag
содержит строки , такие как ДАТА, ВЕС и т. Д.). Затем, используя цикл for, который вызывает
fr_fbdb()
` n раз, получите req. Теги. Я также печатаю значение, которое было получено здесь и в цикле for ниже. Пожалуйста, укажите, где могут быть недостатки., @Somasundharam Sampath_dt
- это локально объявленная переменная, ее область действия остается локальной, и когда вызов возвращается из функции, все, что хранится в_dt
, может быть освобождено и память может быть переопределена., @hcheung"_data" имеет значение, возвращаемое функцией
`fr_fbdb ()
, что подтверждается операторами print в 1-м цикле for` retreive_sch ()
. Во втором цикле for`retreive_sch()
тот же var,
_data
дает разные значения. Я утверждаю, что если бы существовал pblm (bco области действия переменных), то он должен был быть показан в первом операторе печати. (Если вы еще не заметили, я прокомментировал операторы печати в
fr_fbdb()
`), @Somasundharam Sampath