zoukankan      html  css  js  c++  java
  • 转载

    前言:

    使用c库最关心的是内存谁来分配,谁来释放。json-c的内存管理方式,是基于引用计数的内存树(链)。

    如果把一个struct json_object 对象a,add到另一个对象b上, 就不用显式的释放(json_object_put) a了, 相当于把a挂到了b的对象树上, 释放b的时候, 就会释放a。

    当a即add到b上,又add到对象c上时会导致a被释放两次(double free),这时可以增加a的引用计数(调用函数json_object_get(a)),这时如果先释放b,后释放c,当释放b时,并不会真正的释放a,而是减少a的引用计数为1,然后释放c时,才真正释放a。

        理解了上面这点,使用json-c库,基本不会有什么问题了。

    下面是进行分析哪些函数申请了内存:

    1. json_object_get与json_object_put函数 
    struct json_object* json_object_get(struct json_object *jso); // 将json对象的引用计数加1,返回jso自身
    void json_object_put(struct json_object *jso); // 将jso对象的引用计数减1。此时如果json的引用计数大于0,直接返回; 如果json的引用计数为0,则递归的对每个子对象的引用计数减1,子对象引用计数为0时释放所占用内存。
    注:如果对json对象显式调用了json_object_get,之后必须成对调用json_object_put,否则将导致该json对象所占用内存泄漏。

    2. json_object_new_XXX系列函数 struct json_object* json_object_new_object(void);
    struct json_object* json_object_new_int(int i);
    struct json_object* json_object_new_double(double d);
    struct json_object* json_object_new_array(void);
    struct json_object* json_object_new_string(const char *s);
    struct json_object* json_object_new_string_len(const char *s, int len);
    json_object_new_XXX系列函数用来创建XXX类型的json对象,创建的json对象默认引用计数为1,因此在该对象使用完后也需要调用一次json_object_put来把引用计数置0,从而释放内存。

    3. json_tokener_parse函数 
    struct json_object* json_tokener_parse(const char *str);
    json_tokener_parse将符合json格式的字符串构造为一个json对象,构造的json对象默认引用计数为1,同样需要在使用完后对该对象调用一次json_object_put。

    4. is_error宏
    is_error(jso)
    如果传入的字符串是非法的json格式,错误判断应该使用is_error宏,而非 if(NULL != jso),CGI中目前有很多这种错误用法(虽然好像没引发什么问题)


    5. json_object_object_XXX函数
    void json_object_object_del(struct json_object* jso, const char *key);
    从jso对象中删除键值为key的子对象,并释放该子对象及键值所占的内存(注:可能有文档说json_object_object_del只是删除而不释放内存,但实际上这是错误的)。
    struct json_object* json_object_object_get(struct json_object* jso, const char *key); 从jso中获取键值为key的子对象。错误判断同样应该用is_error(jso)宏。
    void json_object_object_add(struct json_object* jso, const char *key, struct json_object *val); 更新键值为key的子项的值。整个过程实际上是这样的:先从jso中删除并释放键值key及其值的内存,然后重新分配内存添加键值和新的值,所以json_object_object_add是包含json_object_object_del操作的。

    6. json_object_get_XXX系列函数 
    struct lh_table* json_object_get_object(struct json_object *jso);
    const char* json_object_get_string(struct json_object *jso);
    int json_object_get_int(struct json_object *jso);
    double json_object_get_double(struct json_object *jso); 这类函数只是获取json对象的实际数据内容,不更新引用计数,也不分配内存。

    7. json_object_array_XXX系列函数
    struct json_object* json_object_array_get_sub_array(struct json_object *jso, int start_idx, int number);
    这个函数用来从一个json数组对象中取数组序号start_idx开始的、总共number长度的子数组对象。分页显示功能常用到。注:返回的子数组是有重新分配内存的,所以同样要对返回的json_object*做一次json_object_put操作来释放内存。
    int json_object_array_add(struct json_object *jso,struct json_object *val); 向数组中添加一个值。
    int json_object_array_length(struct json_object *jso); 获取数组长度。
    int json_object_array_put_idx(struct json_object *jso, int idx, struct json_object *val); 更新数组中序号为idx那一项的值,老的值同样会先被释放。
    struct json_object* json_object_array_get_idx(struct json_object *jso, int idx); 获取数组中序号为idx那一项的json对象,不更新引用计数,也不分配内存。
    struct json_object* json_object_array_sort(struct json_object *jso, const char *keyname, int sord ); 根据键值为keyname的项的值进行升序或降序排序,只是改变数组成员的顺序,不更新引用计数,也不分配内存。

    原文链接https://blog.csdn.net/qiuoooooo/article/details/78643529

  • 相关阅读:
    leetcode Super Ugly Number
    leetcode Find Median from Data Stream
    leetcode Remove Invalid Parentheses
    leetcode Range Sum Query
    leetcode Range Sum Query
    leetcode Minimum Height Trees
    hdu 3836 Equivalent Sets
    hdu 1269 迷宫城堡
    hud 2586 How far away ?
    poj 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/stonemjl/p/13664915.html
Copyright © 2011-2022 走看看