简体   繁体   中英

Printing Allocated cJSON cString inside Struct triggers EXC_BAD_ACCESS (Segmentation Fault) C lang

I can't fix this bug:

After returning the vector struct and printing it (main.c) I get a seg fault. EXC_BAD_ACCESS typically means that the memory address pointed to is not allocated.

But I never deallocated the parsed JSON (cJSON_Delete(cJSON *input_json)). Furthermore when I print everything from the get_album_items function it works.

When I try to access the allocated cstring outside the get_album_items function I get the first items in the array and then rubbish.

Here is the LLDB Trace:

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.

Parse JSON String

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;
  }
}

Vector Struct:

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;
  }
}

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: %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);
    }
  }
}

Thank you for your help!

Update: The dynamic array implementation I used only allocates an array of void pointers that are typecasted when used. Allocating the struct array directly resolved the segfault and is cleaner.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM