Срабатывание 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. |