简体   繁体   English

使用智能指针

[英]Using Smart Pointers

I am working on a legacy C++ app which has the following function, 我正在使用具有以下功能的旧版C ++应用程序,

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. 该应用程序调用一个不同的进程,并获得一个节点ID作为char指针,然后将其传递给CreateNewString函数,以动态地为新字符串分配内存。

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. 但是我想先尝试在C ++ 11中使用智能指针,然后再尝试其他方法。

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. 目的是使函数签名保持不变,即它返回一个char指针,这样我就不必在所有调用位置进行更改。

The above is not working as ptr is released as it's declared inside the scope of this function. 由于在函数的范围内声明了ptr ,因此上述方法不起作用。

My goal is to: 我的目标是:

  1. Use C++ 11 smart pointers to achieve this with minimum code changes to the existing application. 使用C ++ 11智能指针可以在对现有应用程序进行最少代码更改的情况下实现此目的。

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. 但是我想在回到传统的C ++方式之前探索新的C ++功能。 BTW, I am not interested in exploring std::string at this point. 顺便说一句,我对此时的std::string不感兴趣。

You could: 你可以:

  • return the shared_ptr 返回shared_ptr
  • return a std::string 返回一个std::string
  • leave everything as it is 保留一切

Those are your options. 这些是您的选择。

I don't see a way you can have the function return char pointer and still use smart pointers. 我没有找到一种方法可以让函数返回char指针并仍然使用智能指针。 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() 然后调用它的任何地方,只需添加.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 使用std::unique_ptr ,它可以正确删除数组,因此我们不需要自定义删除器

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. 您没有获得任何好处,但是至少可以确保在程序终止之前将内存释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM