Hi Ertan,
On 2019-01-15 10:57 p.m., Ertan Küçükoglu wrote:
> Hello,
>
> Thank you for explanations and suggestion to use Valgrind. My case, I
> cannot use Valgrind because I do not have opportunity to run generated
> executable on linux, windows or else where. It can only be used on
> embedded device itself.
That's not really true: I've been editing your code samples slightly and
running them on my Linux PC, with valgrind.
> My initial post was to read json string. I also build json strings. Some
> of them has json arrays and I do loops. I also wonder if there is any
> leak in my below code:
>
>
> |
> json_t *root;
> json_t *transactions;
> json_t *tmp;
> char*json_result;
>
>
> transactions =json_array();
> i =0;
> while(1)
> {
> if(i >0)
> {
> // if max transmit count reached or final packet
> if((i %MAX_RECORDS_IN_SINGLE_TRANSFER ==0)||(i ==TotalTransactions))
> {
> root =json_object();
Here, you create a new "root" object that needs to (eventually) be
json_decref'd. Since this occurs in a loop, you will probably need more
than one call to json_decref(root). However, you have only one call at
the bottom of the function.
> json_object_set_new(root,"ApiKey",json_string(ApiKey));
> json_object_set_new(root,"ttc",json_integer(TotalTransactions));
>
> json_object_set_new(root,"data",transactions);
For this kind of code, json_pack() is much more compact. You could use
something like:
json_object_set_new(root,
json_pack("s:[s:s,s:i]", "data",
"ApiKey", ApiKey, "ttc", TotalTransactions));
> json_result =json_dumps(root,JSON_COMPACT);
This seems like the last place you use "root" in the loop, and would be
a good place to consider json_decref(root).
> transactions =json_array();
Here, you create a new "transactions" object -- but you only use it if
you enter the next loop iteration. It's easy to leak a single instance
this way, even if your reference counting is otherewise correct. Please
consider initializing "transactions" just before you use it, rather than
at the end of the previous loop iteration.
>
> if(i ==TotalTransactions)
> goto GoOut;
> }
> }
>
> tmp =json_object();
>
> memset(buf,0,sizeof(buf));
> strncpy(buf,tr.TransactionCount,sizeof(tr.TransactionCount));
> json_object_set_new(tmp,"tc",json_string(trim(buf)));
>
> memset(buf,0,sizeof(buf));
> strncpy(buf,tr.TransactionDate,sizeof(tr.TransactionDate));
> json_object_set_new(tmp,"td",json_string(trim(buf)));
>
> json_array_append_new(transactions,tmp);
Again, json_pack() can simplify this kind of code.
>
> i++;
> }
>
>
> GoOut:
> json_decref(root);
> json_decref(tmp);
>
> |
> I am worried about "root, tmp, transaction" obviously. I do not know if
> using json_object_set_new() moves all data and memory clean up
> responsibilities to root as in my initial case.
As the documentation claims, "json_object_set_new()" steals a reference
to the object, so you are transferring ownership of the object to its
new container. You need only decref() the container to free up memory.
I do embedded work, too, and occasionally use mock-ups or other testing
techniques to allow me to run, profile, and test embedded code on a
Linux PC. There is no replacement for the confidence that a proper test
environment gives you. (As a side perk, you will become less reliant on
free code reviews from strangers on the Internet!)
best,
Graeme