Home > Enterprise >  Will there still be a memory leak if I don't store the returned ptr?
Will there still be a memory leak if I don't store the returned ptr?

Time:08-26

I was reading this question, and here the jsoncpp CharReaderBuilder::newCharReader() function returns a pointer to a dynamically created CharReader object, which can then be used to parse a JSON.

I understand in that question the OP should have freed the returned pointer once it was used, since it was created on the heap. But, I am confused about whether, if we never store the returned pointer since it is for 1-time-use only, and write something like this:

Json::Value root;
Json::CharReaderBuilder().newCharReader()->parse(serverResponse.response,
    serverResponse.response   serverResponse.size - 1, &root, &Json::String());

Will this still cause a memory leak? If so, then in this case, I am not storing the pointer, so I cannot really call free() or delete to free that location of memory since I need a reference for that.

I guess I could somehow wrap the entire thing around the C unique_ptr thing, but I think this should not cause any memory leak. Am I correct?

Edit: From the comments, it seems this will still cause a memory leak. So, how should I delete this pointer since I currently have no reference to it? Am I forced to create a reference and store the pointer if I want to avoid a memory leak? Is there no other way?

CodePudding user response:

"The other way" is using smart pointers. Consider the following examples.

#include <iostream>

struct A {
    int b;
  
    A(int _b) :b(_b) { std::cout << "A created." << std::endl; }
    ~A() { std::cout << "A destroyed." << std::endl; }
};

void c(A *a) {
    std::cout << a->b << std::endl; 
}

int main() {
    c(new A(42));

    return 0;
}

Running this:

% ./a.out
A created.
42

That temporary object created is never cleaned up.

#include <iostream>
#include <memory>

struct A {
    int b;
  
    A(int _b) :b(_b) { std::cout << "A created." << std::endl; }
    ~A() { std::cout << "A destroyed." << std::endl; }
};

void c(std::unique_ptr<A> a) {
    std::cout << a->b << std::endl; 
}

int main() {
    c(std::make_unique<A>(27));

    return 0;
}

Here we've use a smart pointer (std::unique_ptr), and we can see that the destructor is called and the temporary is cleaned up.

% ./a.out
A created.
27
A destroyed.

CodePudding user response:

Will this still cause a memory leak?

Yes. The returned pointer is pointing at a new'ed object, so it must be delete'd when you are done using the object.

Am I forced to create a reference and store the pointer if I want to avoid a memory leak?

Yes, eg:

CharReader *reader = Json::CharReaderBuilder().newCharReader();
reader->parse(...);
delete reader;

Which can be wrapped in std::unique_ptr so you don't have to delete it manually, eg:

std::unique_ptr<CharReader> reader(Json::CharReaderBuilder().newCharReader());
reader->parse(...);

Alternatively, for a one-time use, you can use operator-> directly on a temporary unique_ptr instance, eg:

std::unique_ptr<CharReader>(Json::CharReaderBuilder().newCharReader())->parse(...);

Either way, consider using an alias to make the code a little more readable, eg:

using CharReader_ptr = std::unique_ptr<CharReader>;

...

CharReader_ptr reader(Json::CharReaderBuilder().newCharReader());
reader->parse(...);

...

CharReader_ptr(Json::CharReaderBuilder().newCharReader())->parse(...);
  • Related