Программирование ARM: решение проблем, FAQ Срабатывание assert при вызове cJSON_Delete Thu, April 25 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Срабатывание assert при вызове cJSON_Delete Печать
Добавил(а) microsin   

Делаю на ESP32 парсинг JSON-строки, которая приходит от сервера, чтобы извлечь оттуда URL. Столкнулся с ошибкой освобождения памяти при вызове cJSON_Delete.

  do
  {
    jroot = cJSON_Parse(src);
    if (NULL == jroot)
      break;
// здесь все норм
    jurl = cJSON_GetObjectItem(jroot, "fw_url");
    if (NULL == jurl)
      break;
// здесь все норм
    if(!cJSON_IsString(jurl) || NULL == jurl->valuestring)
      break;
// здесь все норм, делаю копию jurl->valuestring
    strcpy(dst, jurl->valuestring);
    result = true;
  } while (false);
 
  if (jurl)
    cJSON_Delete(jurl);  // здесь все норм
  if (jroot)
    cJSON_Delete(jroot); // а вот тут падение программы

В логе сообщение об ошибке:

assert failed: 0x4038ef6a
0x4038ef6a: tlsf_free at ~/esp-idf/components/heap/heap_tlsf.c:872 (discriminator 1)

Посмотрел в heap_tlsf.c строку 872, срабатывает вот этот assert:

tlsf_assert(!block_is_free(block) && "block already marked as free");

Причина оказалась в особенности реализации библиотеки cJSON. Необходимо удалять только родительский объект (в этом примере jroot), потому что удаление родительского объекта автоматически удалит дочерние объекты (в этом примере jurl). Вызов cJSON_Delete(jroot) пытался удалить дочерний объект jurl, который уже был удален, поэтому возникала ошибка.

Исправление ошибки:

  //if (jurl)
  //  cJSON_Delete(jurl);
  if (jroot)
    cJSON_Delete(jroot);

Основное правило удаления объектов cJSON: не надо удалять дочерние объекты.

[Ссылки]

1. DaveGamble / cJSON site:github.com.
2. xuzd / cJSON site:gitee.com.

 

Добавить комментарий


Защитный код
Обновить

Top of Page