Как проверить, был ли указатель cJSON инициализирован / установлен ранее? - PullRequest
1 голос
/ 17 января 2020

У меня есть структура с cJSON указателями, как в:

  struct { 

      cJSON *myJSON1;
      cJSON *myJSON2;
      ...
  } myStruct;

Где-то в моем коде я создаю cJSON элементов, как в myStruct.myJSON1 = cJSON_CreateObject ()

В конце кода я хочу вызвать cJSON_Delete () для тех указателей, которые были назначены. Я предполагаю, что это случай classi c C, в котором нет способа узнать, был ли указатель каким-либо образом неправильно размещен. Конечно, я могу сохранить флаг, чтобы отслеживать, но я хочу простой способ. Я прочитал ...

Структура cJSON имеет вид:

  /* The cJSON structure: */
  typedef struct cJSON
  {
      struct cJSON *next;
      struct cJSON *prev;
      struct cJSON *child;
      int type;
      char *valuestring;
      /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
      int valueint;
      double valuedouble;
      char *string;
  } cJSON;

Доступна функция cJSON_Invalid () . Документация гласит: «(проверьте cJSON_IsInvalid): представляет недопустимый элемент, который не содержит никакого значения. У вас автоматически появляется этот тип, если вы устанавливаете для элемента все нулевые байты». Должен ли я установить для структуры значение 0 или просто набрать?

Другими словами, мой вопрос таков: какой самый простой способ проверить, является ли указатель cJSON неправильным, без создания дополнительного переменная? Возможно, установить «тип» на ноль? Я могу попробовать такие варианты, но я хочу определенный ответ, который работает во всех ситуациях.

1 Ответ

1 голос
/ 22 января 2020

Если у вас просто есть неинициализированный указатель на структуру данных cJSON, поведение не определено. Т.е. для cJSON *myJSON1;

cJSON_Invalid(myJSON1) может возвращаться 0 или 1.

И cJSON_Delete(myJSON1) вероятно будет сегфоутом. Или ничего не делать, если вам повезет.

Решение состоит в том, чтобы всегда инициализировать cJSON структур данных в NULL. Тогда вы можете просто позвонить cJSON_Delete(). Если указатель все еще NULL, вызов ничего не сделает. Если он был установлен в какой-то момент в вашей программе, он правильно освободит всю память. Поскольку у вас есть структура из нескольких cJSON указателей, вы можете установить всю структуру данных на 0, используя memset.

Вы можете взглянуть на исходный код .

CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
{
    cJSON *next = NULL;
    while (item != NULL)
    {
    ...
    }
}
...