Chances of memory leak in cJSON_Print in CPP [duplicate] - c++

I am using the cJSON library and I have a function as follows:
void printJsonObject(cJSON *item)
{
char *json_string = cJSON_Print(item);
printf("%s\n", json_string);
}
Will this function leak memory?

I've never used cJSON , but as per the function definition present in this link, it looks like
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
and
static char *print_value(cJSON *item,int depth,int fmt);
From print_value() function, the pointer returned is allocated by cJSON_strdup() [which is a modified version of the combination of malloc() and memcpy()] and it is returned to the caller.
As I see no method to track the allocation, IMO, the allocated memory needs to be free()d by the caller function. Otherwise, it will be a memory leak.

Yes, it is a memory leak.
Buffers returned by cJSON_Print must be freed by the caller. Please use the proper API (cJSON_free) rather than directly calling stdlib free.
See the cJSON maintainer's comment: https://github.com/DaveGamble/cJSON/issues/5#issuecomment-298469697
I recommend:
void printJsonObject(cJSON *item)
{
char *json_string = cJSON_Print(item);
if (json_string)
{
printf("%s\n", json_string);
cJSON_free(json_string);
}
}

Related

using "new" and "delete" inside class function

I want to be sure that using new and delete to free heap memory is done as needed.
Following function returns a char *. Inside each function I use new for the returned value, and I delete afterwards.
Is it the right way to free heap memory for function return?
const char *myIOT2::_devName()
{
char *ret = new char[MaxTopicLength2];
if (strcmp(addGroupTopic, "") != 0)
{
snprintf(ret, MaxTopicLength2, "%s/%s/%s", prefixTopic, addGroupTopic, deviceTopic);
}
else
{
snprintf(ret, MaxTopicLength2, "%s/%s", prefixTopic, deviceTopic);
}
return ret;
}
const char *myIOT2::_availName()
{
char *ret = new char[MaxTopicLength2];
const char *DEV = _devName();
snprintf(ret, MaxTopicLength2, "%s/Avail", DEV);
delete DEV;
return ret;
}
To point out: the fact the I DEV: const char *DEV = _devName(); in order to use it as a parameter in snprintf(ret, MaxTopicLength2, "%s/Avail", DEV); just to be able to delete it later as delete DEV; - is this correct?
At least as I see things, you really only have two sane choices here. One is for the caller to handle all the memory management. The other is for the callee to handle all the memory management.
But what you're doing right now (callee handles allocation, caller handles de-allocation) is a path to madness and memory leaks.
If the caller is going to manage the memory, this all becomes fairly simple:
const char *myIOT2::_devName(char *ret, size_t maxlen)
{
if (strcmp(addGroupTopic, "") != 0)
{
snprintf(ret, maxlen, "%s/%s/%s", prefixTopic, addGroupTopic, deviceTopic);
}
else
{
snprintf(ret, maxlen, "%s/%s", prefixTopic, deviceTopic);
}
return ret;
}
If the callee is going to handle all the memory management, you'd normally use std::string. Since you're on an Arduino, however, std::string isn't available, and you need to use their own String class instead. Either way, you simply allocate a String object and put your contents into it. It takes care of the actual memory allocation to hold the contents, and will free its contents when the String object is destroyed.
Given the small amount of memory normally available on an Arduino, having the caller allocate the memory is usually going to work out better. But (especially if this is something that doesn't happen very often, so you won't run into heap fragmentation problems) allocating space on the heap can work reasonably well also.
But I'll repeat: trying to mix memory management so the callee allocates and the caller deletes...is the stuff of nightmares. When you read about C++ circa 1993, and hear about lots of problems with memory leaks...this is exactly the sort of thing that led to them.
ret allocated memory:
const char *myIOT2::_devName()
{
char *ret = new char[MaxTopicLength2];
return ret;
}
And below, you'll see that by deleting DEV, you will free the memory, because it's actually ret. But this time, you should remove ret2 somewhere else since it's the return value and there's no way to delete it inside that scope:
const char *myIOT2::_availName()
{
char *ret2 = new char[MaxTopicLength2];
const char *DEV = _devName();
delete[] DEV;
return ret2;
}
Also, note the following:
char* str = new char [30]; // Give str a memory address.
// delete [] str; // Remove the first comment marking in this line to correct.
str = new char [60]; /* Give str another memory address with
the first one gone forever.*/
delete [] str; // This deletes the 60 bytes, not just the first 30.

C++ release allocated char* into string

I have tried to find an answer but couldn't see anything straight forward.
How do I free the allocated memory in the next snippet code:
const char* attStr = strdup(OtherCharStr);
string str(attStr, strlen(attStr));
delete str; //???
C++ uses idiom called RIAA - Resource Acquisition Is Initialization. It means that object lifetime is driven by variable scope.
{
std::string s("foo"); // variable s declaration and string initialization
do_some_stuff(s);
// end of scope of variable s - it is destroyed here
// no need to free(s) or whatever
}
// variable s and the string doesn't exist here, no memory for it is allocated
This applies only for C++ objects that maintain its resources properly (are freeing them in the destructor). Simple pointers doesn't do it - you have to free them yourself:
const char *attStr = strdup(...);
// do something with attStr
free(attStr); // because strdup() documentation says you should free it with free()
Also notice that C++ uses new and delete rather than malloc() and free():
std::string *strPointer = new std::string(...);
// RIAA doesn't work here, because strPointer is just plain pointer,
// so this is the case when you need to use free() or delete
delete strPointer;
I recommend to read something about smart pointers which are deleting the object they point to automatically. I'm getting pretty far from the original question but this topic is important to understand how C++ works.
You need to release attStr not the c++ string that will release its resources alone.
void func()
{
const char* attStr = strdup(OtherCharStr);
string str(attStr, strlen(attStr));
free(attStr);
}//here str will release its own resources
Also you can do
string str = OtherCharStr;
an that's it. Only check what happens with OtherCharStr

Free allocated pointer passed to a function?

When shall I free my unsigned char* if I need to pass the unsigned char* into a function?
Example
void myFunction(unsigned char *request){
// do I need to use free(request); here?
}
int main (){
// main code
unsigned char *request = NULL;
// read from buffer and reallocate memory (using realloc & memcpy)
myFunction(request); // I do not want to read or use "request" after this function call.
free(request); // is this ok? Or should this be inside myFunction also?
return 0;
}
Use free() on something as soon as you're done using it. So for instance, you probably wouldn't do it inside myFunction() because you're probably still going to be interested in the value pointed at by request when you exit that function back to main.
Usually you have to free it where you have allocated it, and don't need more it.
In This case you can do it in both places, but also, after freed set it to NULL, and next time when you'll try to free it, check for null
also you mai implement something like:
void FreeAndNull(void *request){
if request <> NULL then
{ free(request); request = NULL; }
}
You don't have to do this - but a good practice is to free things at the same level as you allocated them. E.g. don't allocate something in a function and free it after it is returned. Because then the lifecycle of the memory is not clear to you months later when you look at the code again.
So it is much better to:
request = malloc();
doStuff( request );
free( request );
than the pattern you have. C++ helps you with this pattern by creating constructors and destructors. That is a constructor may actually allocate memory and essentially return it to you in the form of an object, but the compiler will automatically call the destructor for you freeing the memory.
So you can achieve something like the pattern you want with a much safer and more maintainable pattern if you wrap that request buffer in a class:
Request::Request() { mRequest = malloc(); }
Request::~Request() { if ( mRequest ) free( mRequest ); mRequest = NULL; }
...
{
Request request;
myFunction( request );
}
With this pattern you memory is cleaned up automatically. Safer and more maintainable.

How to return local array in C++?

char *recvmsg(){
char buffer[1024];
return buffer;
}
int main(){
char *reply = recvmsg();
.....
}
I get a warning:
warning C4172: returning address of local variable or temporary
I would suggest std::vector<char>:
std::vector<char> recvmsg()
{
std::vector<char> buffer(1024);
//..
return buffer;
}
int main()
{
std::vector<char> reply = recvmsg();
}
And then if you ever need char* in your code, then you can use &reply[0] anytime you want. For example,
void f(const char* data, size_t size) {}
f(&reply[0], reply.size());
And you're done. That means, if you're using C API, then you can still use std::vector, as you can pass &reply[0] to the C API (as shown above), and reply to C++ API.
The bottomline is : avoid using new as much as possible. If you use new, then you've to manage it yourself, and you've to delete when you don't need it.
You need to dynamically allocate your char array:
char *recvmsg(){
char* buffer = new char[1024];
return buffer;
}
for C++ and
char *recvmsg(){
char* buffer = malloc(1024);
return buffer;
}
for C.
What happens is, without dynamic allocation, your variable will reside on the function's stack and will therefore be destroyed on exit. That's why you get the warning. Allocating it on the heap prevents this, but you will have to be careful and free the memory once done with it via delete[].
The warning message is correct. You're returning the address of a local array which disappears after the function returns.
You can do this using dynamic memory allocation:
char *recvmsg(){
char *buffer = (char*)malloc(1024);
return buffer;
}
The catch is that you need to make sure you free() the pointer later on to avoid a memory leak.
Alternatively, you can pass the buffer into the function.
void recvmsg(char *buffer,int buffer_size){
// write to buffer
}
void main(){
char buffer[1024];
recvmsg(buffer,1024);
}
This avoids the need for a memory allocation. This is actually the preferred way to do it.
The problem is that buffer lives on the stack and goes out of scope the moment you exit recvmsg.
You could allocate buffer on the heap:
char *recvmsg(){
char *buffer = malloc(1024);
return buffer;
}
Note that now the caller is responsibe for disposing of the allocated memory:
void main(){
char *reply = recvmsg();
free(reply);
}
You have a few options...The way you're doing it now is going to cause undefined behavior as the array will go out of scope once hte function returns. So one option is to dynamically allocate the memory..
char * recmsg()
{
char * array = new char[128];
return array;
}
Just remember to clean it up with delete this way (or free if you used malloc). Second, you could use a parameter...
void recmsg(char * message, int size)
{
if (message == 0)
message = new char[size];
}
Again, the same thing goes for clean up here as with the previous. Also note the check for 0 to make sure you don't call new on a pointer that's been allocated already.
Last, you could use a vector..
std::vector<char> recmsg()
{
std::vector<char> temp;
//do stuff with vector here
return temp;
}
char *recvmsg(){
char *buffer = new char;
cout<<"\nENTER NAME : ";
cin>> buffer;
return buffer;
}
int main(){
char *reply = recvmsg();
cout<<reply;
}
Just to complete the picture:
It is not necessary, to allocate memory with malloc. You can also create the buffer on the stack, but you must create it on a stack frame that lives as long as the consumer of the buffer lives. That was the error of the OP -- when the callee was finished, the buffer was deleted and the caller got a invalid pointer.
So what you can do is this:
void recvmsg(char *buffer, size_t size) {
... do what you want ...
}
void main(void) {
char buffer[1024];
recvmsg(buffer, sizeof(buffer));
}
You could dynamically create the buffer, but then the caller needs to know to free it.
I think it's better to pass in a buffer (assuming recvmsg also fills it)
void recvmsg(char *buffer, size_t size){
}
void main(){
char buffer[1024];
recvmsg(buffer, sizeof(buffer));
}
Even if the caller decides dynamic is better, they will know that they need to free it, and the specific way to do that (free(), delete, delete[], or perhaps something special from a custom allocator)
The problem is that you are returning a pointer to a buffer allocated on the stack. Once the function returns, that buffer is no longer valid.
You are allocating the array on the stack inside of your recvmsg function. Returning a pointer to that memory will at some point lead to undefined behavior if it is dereferenced as the memory will be cleaned up when the function exits.
If you want to return a pointer to memory you will need to allocate it dynamically using malloc.
when you are returning the buffer then as it acting as a pointer to the first location of the array so it will return its address.And the place where you are calling the function there you can make a character pointer which will store this returned address value .After which you can move your pointer and can access all the elements of your array.
how about passing by ref
char buf[1024];
PutStuffInBuff(&buf);

Destructor on const char *

In my program, i have line like this:
const char * str = getStr();
Do i need to call destructor on str [] at the end of function to prevent memory leaks?
Question does not contain enough information to tell, it depends what getStr() does. For example:
const char *getStr() {
return "boo";
}
then you must not call delete.
const char *getStr() {
return new char;
}
then you should call delete str; to avoid a memory leak (and must not call delete[]).
const char *getStr() {
return new char[10];
}
then you should call delete[] str; to avoid a memory leak (and must not call delete).
const char *getStr() {
return 0;
}
then it doesn't matter what you do, calling any kind of delete on str has no effect.
Ownership of resources, and how to release any resources owned, are part of the interface to a function, and should be documented at the same time as you document what the return value actually is.
It all depends on what getStr() does. It may even be that you have to call free on the pointer if getStr() created it with malloc. It may be that getStr() is returning a pointer to a static area (not very thread safe, but it happens) or any number of other things.
Part of the contract and documentation for getStr() should be who owns the pointer it returns.
Here are some examples of possible getStr() functions...
In this case getStr() owns the pointer and you don't have to do anything to free it. OTOH, what's being pointed at may change the next time you call getStr() so you should probably make your own copy if you need to keep it around for any length of time:
const char *getStr()
{
static char buf[30] = "Silly counter";
buf[0] = buf[0] + 1;
return buf;
}
In this case, you will eventually need to call free on the pointer returned:
const char *getStr()
{
return strdup("Silly string");
}
In this case, you will need to call plain old delete on the pointer returned:
const char *getStr()
{
return new char;
}
In this case, you will need to call delete [] on the pointer returned:
const char *getStr()
{
return new char[50];
}
There are many other possibilities. As I stated previously, part of the contract for a function (which should appear in its documentation) is who owns the pointer returned and how that data pointed to must be disposed of if doing so is the caller's responsibility.
It depends on how getStr() has been designed. It could return a pointer to a string that is still owned by someone else (and in this case the answer is no) or it may return a pointer to and the caller becomes the owner (and in this case the answer is yes).
You should check the documentation of getStr to know.
If the ownership of the returned area is of the caller then probably in C++ returning an std::string would have been a much better idea.
It's a good idea to do so if it's going out of scope. I'd recommend also setting the pointer to null to ensure it isn't dangling:
delete[] str;
str = null;