I am working on a legacy C++ app which has the following function,
char* CreateNewString (const char* node)
{
int len = (int) strlen(node) + 1;
char * ptr = new char [len];
strcpy_s(ptr, len, node);
return ptr;
}
This function is called from many classes in the app and here's an example use case.
char * nodeID = obj.CreateNewString(process->GetNodeID());
The app calls a different process and get a node ID as char pointer and then passes it to CreateNewString function to dynamically allocate memory for a new string.
Nowhere in the app after the above call, it's deleting the memory. From what I observe, there's a definite memory leak here.
I think there're few ways of resolving this issue. But I want to explore using the smart pointers in C++11 first before trying anything else.
What I Tried:
So I came up with following function:
char* CreateNewString (const char* node)
{
int len = (int) strlen(node) + 1;
shared_ptr<char> ptr (new char [len](), [](char* p) {delete [] p;});
strcpy_s(ptr.get(), len, node);
return ptr.get();
}
The goal is to keep function signature the same, ie it returns a char pointer, so that I don't have to make changes at all calling places.
The above is not working as ptr is released as it's declared inside the scope of this function.
My goal is to:
An alternative way I am aware of is to dynamically initialize array in calling places itself and then delete it before end of that scope. But I want to explore new C++ features before going back to traditional C++ way. BTW, I am not interested in exploring std::string
at this point.
You could:
shared_ptr
std::string
Those are your options.
I don't see a way you can have the function return char pointer and still use smart pointers. There could be potential hacks on getting it done, but all of them have overheads and more importantly, unnecessary code. My suggestion is for a simple change on the new function you wrote and then do another even more simpler change at all calling places.
So the function will look like this,
shared_ptr<char> CreateNewString (const char* node)
{
int len = (int) strlen(node) + 1;
shared_ptr<char> ptr (new char [len](), [](char* p) {delete [] p;});
strcpy_s(ptr.get(), len, node);
return ptr;
}
And then anywhere it get's called, simply add a .get()
char * nodeID = obj.CreateNewString(process->GetNodeID()).get();
This is kind of a hack, but it will work and you will not have a memory leak. What you can do is add a static vector of smart pointers and then when you call the function you store the pointer in the vector so that it won't go out of scope at the end of the function. That would look like
char* CreateNewString (const char* node)
{
std::size_t len = strlen(node) + 1;
static std::vector<std::unique_ptr<char[]>> data_pool; // static pool, destroyed at end of program
data_pool.push_back(std::unique_ptr<char[]>(new char [len]{})); // add pointer to pool
strcpy_s(data_pool.back().get(), len, node); // copy the string
return data_pool.back().get(); // return pointer to the managed data
}
using a std::unique_ptr
, which deletes arrays correctly so we don't need a custom deleter
Do note that using this solution you wont have a memory leak, but all of the allocated memory will last until the end of the program. You don't gain anything, but at least you are guaranteed the memory is deallocated before the program terminates.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.