[jansson-users] Completely free a json object

3,999 views
Skip to first unread message

Taris

unread,
May 20, 2010, 9:50:38 AM5/20/10
to Jansson users
Hi list!

My program builds up a json object entirely from scratch, as long as
there is no json string to parse.
After building and dumping the json string i had my problems to
entirely free the object (and all subobjects, -arrays,...) without
memory leaking.
So i build a recursive function to walk through all levels and
depending on the type freeing the json_t object in it.

It worked quite well and my program was reusing the existing json
string by parsing it and restoring the json object it build before.
Now it was possible to modify the data and dumping it as a new json
string.
After doing that the program had to free all the memory again and now
the recursive function is causing "write"-errors in valgrind telling
me that i am doing unallowed writes - it works, when i build up the
json object from scratch without loading an already existing string.

So i was wondering - does the json_loads() function the allocating of
memory differently than loading and inserting the json_object() and
json_array() one by one?
Is there a general function that frees a json construct entirely -
without memory leaking and causing write errors? :)

Thx Taris

--
Jansson users mailing list
jansso...@googlegroups.com
http://groups.google.com/group/jansson-users

Petri Lehtinen

unread,
May 20, 2010, 10:01:20 AM5/20/10
to jansso...@googlegroups.com
Jansson has a reference counting mechanism that automatically manages
the memory of JSON values, as long as you call json_decref() on all
values you hold a reference to. You must never free() any json_t
pointer by yourself; json_decref() does this when the reference count
drops to zero.

A JSON object takes a reference of each of its children. Invoking

json_decref(object);

decreases the reference count of each child if the reference count of
object drops to zero. You don't have to go through the structures
yourself.

When you build up an object by hand, you probably do something like
this:

json_t *object = json_object();
json_object_set(object, "foo", json_integer(15));

This leaks memory, as json_integer() returns a new reference to an
integer value, and json_object_set() increases its reference count.
When you call

json_decref(object);

the reference count of the integer value inside the object gets
decreased by one, but still doesn't drop to zero. Instead, you need to
call

json_object_set_new(object, "foo", json_integer(15));

if you're not going to call json_decref() on the integer value by
yourself. Note the "_new" suffix in the function name. All the _new
functions steal the reference to the value that's being added to the
object (or array), so you basically let the container object fully
manage the reference counting.

Petri

Taris

unread,
May 20, 2010, 10:10:07 AM5/20/10
to Jansson users
Hi Petri and thx for the fast answer!

> Jansson has a reference counting mechanism that automatically manages
> the memory of JSON values, as long as you call json_decref() on all
> values you hold a reference to. You must never free() any json_t
> pointer by yourself; json_decref() does this when the reference count
> drops to zero.
Sorry, i didn't write that, but i already do that way. I am not
freeing the objects directly but call json_decref() for every json_t
object in the entire structure.

> When you build up an object by hand, you probably do something like
> this:
>
>   json_t *object = json_object();
>   json_object_set(object, "foo", json_integer(15));
Correct - i do it that way - and even put that into an array.
Basically i have an array of timestamps, that is in an object, which
is again in an object.

> the reference count of the integer value inside the object gets
> decreased by one, but still doesn't drop to zero. Instead, you need to
> call
>
>   json_object_set_new(object, "foo", json_integer(15));
>
> if you're not going to call json_decref() on the integer value by
> yourself. Note the "_new" suffix in the function name. All the _new
> functions steal the reference to the value that's being added to the
> object (or array), so you basically let the container object fully
> manage the reference counting.

Ok, so i just use the "_new"-functions and keep the recursive
function? I will try that.
Thx for the help!

Deron Meranda

unread,
May 20, 2010, 11:26:50 AM5/20/10
to jansso...@googlegroups.com
On Thu, May 20, 2010 at 10:01 AM, Petri Lehtinen <pe...@digip.org> wrote:
> When you build up an object by hand, you probably do something like
> this:
>
>  json_t *object = json_object();
>  json_object_set(object, "foo", json_integer(15));
>
> This leaks memory, as json_integer() returns a new reference to an
> integer value, and json_object_set() increases its reference count.


Petri, I know this is documented, but the examples you present
here in your email response are very clear and lucid; and
this is a type of mistake I'm sure is very easy for people to
unknowingly make.

Perhaps you can incorporate some of this extra explanation
into the docs to make it even clearer?

The current docs mention that some functions may "steal"
references, but leaves it to the reader to find them. Aside
from perhaps showing an example of a bad practice,

json_object_set( object, "foo", json_integer(15))

and the good practice,

json_object_set_new( object, "foo", json_integer(15))

it may also be nice to just list all the "stealing" functions
and the non-stealing counterparts in one place in the
Reference Counting section, e.g.,

json_object_set / json_object_set_new
json_object_set_nocheck / json_object_set_new_nocheck
json_array_set / json_array_set_new
json_array_append / json_array_append_new
json_array_insert / json_array_insert_new

Thanks
--
Deron Meranda
http://deron.meranda.us/

Petri Lehtinen

unread,
May 20, 2010, 11:51:44 AM5/20/10
to jansso...@googlegroups.com
Thanks for the suggestion. I added to the reference counting section
an example of the hard way, without using a reference stealing
function, and another of the easy way with a reference stealing
function. I don't really want to add an example that leaks memory to
the documentation, as a user might accidentally use it!

I also didn't explicitly add a list of functions, just added a note
about the naming of the reference stealing functions.

git: commit 978a47e2c52cca0999bbc8eb6d35674d4931ed5c
git: Author: Petri Lehtinen <pe...@digip.org>
git: Date: Thu May 20 18:45:06 2010 +0300
git:
git: Clarify the documentation on reference stealing
git:
git: Provide an example usage pattern for reference stealing functions.
git: This way the user (hopely) sees more clearly how the reference
git: stealing functions are meant to be used.
git:
git: doc/apiref.rst | 28 +++++++++++++++++++++++++---
git: 1 files changed, 25 insertions(+), 3 deletions(-)

Avdut

unread,
Jul 17, 2012, 5:56:00 AM7/17/12
to jansso...@googlegroups.com

Hi,

   The reference mechanism which has been implemented is totally cool but if only we could know what is the reference count at a particular point in the program will be of very much use !
   Isn`t their any way to know the count at a time ..?
Reply all
Reply to author
Forward
0 new messages