Печать выделенной cJSON CString внутри структуры запускает EXC_BAD_ACCESS (ошибка сегментации) C lang

#c #segmentation-fault #cjson

#c #сегментация-ошибка #cjson

Вопрос:

Я не могу исправить эту ошибку:

После возврата векторной структуры и ее печати (main.c) я получаю ошибку seg. EXC_BAD_ACCESS обычно означает, что указанный адрес памяти не выделен.

Но я никогда не освобождал обработанный JSON (cJSON_Delete(cJSON *input_json)). Кроме того, когда я печатаю все из функции get_album_items, это работает.

Когда я пытаюсь получить доступ к выделенной cstring вне функции get_album_items, я получаю первые элементы в массиве, а затем мусор.

Вот трассировка LLDB:

 Process 1937 launched: '/Users/hugo/Git/libopenTIDAL_Dynamic/tests/a.out' (x86_64)
Testing: At Night
Testing: Floating Dogs
Testing: Quiet And Alone
Testing: Close-Up
Testing: Slow Water
Testing: Dressing The Wound
Testing: Birdy's Flight
Testing: Slow Marimbas
Testing: The Heat
Testing: Sketchpad With Trumpet And Voice
Testing: Under Lock And Key
Testing: Powerhouse At The Foot Of The Moutain

Items: 12
TotalNumberOfItems: 12
Limit: 50
Current Index: 0
Title: At Night
Current Index: 1
Title: Floating Dogs
Current Index: 2
Title: Quiet And Alone
Current Index: 3
Title: Close-Up
Current Index: 4
Title: Slow Water
Current Index: 5
Title: Dressing The Wound
Current Index: 6
Title: uM����
Current Index: 7
Title: `j
Current Index: 8
Title: The Heat
Current Index: 9
Title: L�E��E�
Current Index: 10
Process 1937 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
    frame #0: 0x00007fff203885d2 libsystem_platform.dylib`_platform_strlen   18
libsystem_platform.dylib`_platform_strlen:
->  0x7fff203885d2 < 18>: pcmpeqb (%rdi), %xmm0
    0x7fff203885d6 < 22>: pmovmskb %xmm0, %esi
    0x7fff203885da < 26>: andq   $0xf, %rcx
    0x7fff203885de < 30>: orq    $-0x1, %rax
Target 0: (a.out) stopped.
 

Разбор строки JSON

 void parse_string(cJSON *object, char **string)
{
  if (cJSON_IsString(object) amp;amp; (!cJSON_IsNull(object)))
  {
    /* object->valuestring was allocated by cJSON */
    *string = object->valuestring;
  }
  else
  {
    *string = NULL;
  }
}
 

Векторная структура:

 typedef struct vector
{
  void **items;
  int capacity;
  int total;
  int status;
  size_t limit;
  size_t offset;
  size_t totalNumberOfItems;
  void *json;
  void *jsonManifest;
} vector;
 

Get_Album_Items:

 vector get_album_items(const size_t albumid, const size_t limit, const size_t offset)
{
  vector v;
  char *endpoint;
  char baseparams[50];

  /* allocate vector in heap (init size 4) */
  vector_init(amp;v);

  /* concatenate url endpoint amp; baseparams */
  endpoint = url_cat("albums/", albumid, "/items", 0);
  snprintf(baseparams, 50, "countryCode=%samp;limit=%zuamp;offset=%zu", countryCode,
            limit, offset);
  
  /* perform request */
  curl_model req = curl_get(endpoint, baseparams);
  free(endpoint);
  if (req.status != -1)
  {
    /* parse returned json with cJSON */
    cJSON *input_json = json_parse(req.body);
    if (req.responseCode == 200)
    {
      cJSON *items = cJSON_GetObjectItem(input_json, "items");
      cJSON *item = NULL;
      cJSON *limit = cJSON_GetObjectItem(input_json, "limit");
      cJSON *offset = cJSON_GetObjectItem(input_json, "offset");
      cJSON *totalNumberOfItems = cJSON_GetObjectItem(input_json, "totalNumberOfItems");
      size_t i = 0;

      if (cJSON_IsArray(items))
      {
        items_model track[cJSON_GetArraySize(items)];
        cJSON_ArrayForEach(item, items)
        {
          cJSON *innerItem = cJSON_GetObjectItem(item, "item");
          
          /* parse json values */
          json_items_model processed_json = json_parse_items(innerItem);
          /* parse values to items_model struct*/
          track[i] = parse_items_values(processed_json, i);
          
          /* add items_model struct to vector */
          vector_add(amp;v, amp;track[i]);

          i  = 1;
        }
      }

      parse_number(limit, amp;v.limit);
      parse_number(offset, amp;v.offset);
      parse_number(totalNumberOfItems, amp;v.totalNumberOfItems);

      v.status = 1;
    }
    else
    {
      v.status = parse_status(input_json, req, albumid, NULL);
    }

    v.json = input_json;
    free(req.body);
    return v;
  }
  else
  {
    free(req.body);
    v.status = -1;
    fprintf(stderr, "[Request Error] Album %zu: CURLE_OK Check failed.n", albumid);
    return v;
  }
}
 

Main.c

 int main()
{
  init("/Users/hugo/Documents/oT-config.json");

  vector tracks = get_album_items(93560013, 50, 0);
  if (tracks.status == 1)
  {
    printf("Items: %dn", tracks.total);
    printf("TotalNumberOfItems: %zun", tracks.totalNumberOfItems);
    printf("Limit: %zun", tracks.limit);
    int i;

    for (i = 0; i < tracks.total;   i)
    {
      items_model *Value;
      Value = (items_model *)tracks.items[i];
      printf("Current Index: %dn", i);
      printf("Title: %sn", Value->title);
    }
  }
}
 

Спасибо за вашу помощь!

Комментарии:

1. vector не объявлено

2. @stark да, это так. Я также могу предоставить структуру typedef.

3. Полный обратный путь (вы компилируете с включенной отладочной информацией, верно?) было бы полезно.

4. v.items никогда не устанавливается

Ответ №1:

Обновление: используемая мной реализация динамического массива выделяет только массив указателей void, которые при использовании присваиваются типам. Выделение массива struct напрямую устраняет ошибку segfault и является более чистым.

 int capacity = 4;
items_model *item = (items_model *) malloc(sizeof(items_model)* capacity);