0

我无法修复此错误:

返回向量结构并打印它(main.c)后,我得到一个段错误。EXC_BAD_ACCESS 通常意味着指向的内存地址没有分配。

但我从未释放解析过的 JSON (cJSON_Delete(cJSON *input_json))。此外,当我从 get_album_items 函数打印所有内容时,它可以工作。

当我尝试在 get_album_items 函数之外访问分配的 cstring 时,我得到数组中的第一个项目,然后是垃圾。

这是 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) && (!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(&v);

  /* concatenate url endpoint & baseparams */
  endpoint = url_cat("albums/", albumid, "/items", 0);
  snprintf(baseparams, 50, "countryCode=%s&limit=%zu&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(&v, &track[i]);

          i += 1;
        }
      }

      parse_number(limit, &v.limit);
      parse_number(offset, &v.offset);
      parse_number(totalNumberOfItems, &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;
  }
}

主程序

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

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

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

谢谢您的帮助!

4

1 回答 1

0

更新:我使用的动态数组实现只分配了一个 void 指针数组,这些指针在使用时会进行类型转换。分配struct数组直接解决segfault,更干净。

int capacity = 4;
items_model *item = (items_model *) malloc(sizeof(items_model)* capacity);
于 2020-12-14T13:10:06.407 回答